As far as I know the white (empty) bar represents idle time.
I know I should focus so that the application would run (at best) > 60fps and at least >30fps
This is my bar:
As you can see, I'm repainting on scroll ( changing the background position of an image ).
The middle line marks 60fps in this case, and if you pay attention closely, there is a top line (which is 30fps).
I've compared my results with others out there, and it seems that I have rather large idle times. Is that okay ? I know that paint, javascript and anything else is bad, but what purpose does displaying idle times serve ? Should I attempt to get rid of it, if so, what should I watch out for ?
Also, there is a spike every now and then because of "Image Decode", is there anything I can do about it ?
Image Decode
You can reduce the size of the image, which will make the decodes shorter. You can also trick the browser into doing these decodes earlier, perhaps at a time when there's no activity and therefore won't hurt your FPS.
I would also kill these big images temporarily to see if that moves you from 30fps to 60fps.
Scroll handler
You should minimize the amount of work you're doing in your scroll handler. At most you should be grabbing one scroll metric from the DOM and a timestamp perhaps. Then do your adjustments to style in a requestAnimationFrame loop: http://www.hesslerdesign.com/blog/javascript/optimizing-javascript-performance-handling-coordinate-updates/
Heavy paints
background-position isn't optimized well in WebKit or Blink, especially for this sort of usecase. I would put the image into a div and just slide its position using a transform: translate(x,y) (and promote it to its own layer if possible.) If sucessful, you won't repaint the entire screen on every scroll.
30 FPS Aint bad
A solid 30FPS actually looks better than something that's jumping between 60 and 45 all the time. Curious.. Are you in Canary or on a retina screen?
In general, you're doing pretty okay on your hardware, but I would try to reduce those image decodes. And you can go further with the above if you want.
Related
I am building a website for me and I care about performance, speed, user experience and a lot more. When I started I didn't know much and I made an initial design using adobe xd. Then using webexport plugin I got a html file that has 2k+ lines of codes for scale to fit any screen and proportional resize of everything. I think I made a 1080p standard artboard but somehow it was way too big like 3554px by 2216px. So the webpage is now that big and scaling is running on it. I don't think it's too big for a browser to handle. Things were good before chrome 97 or 96 update. After that chrome and any browser running on chromium just can't scale my webpage fast enough to fit the screen. I see big divs getting smaller and it takes kinda like 500 ms to settle with decent setup. A lot of variables can affect the performance like if the machine(pc) and network is slow the scaling takes couple of seconds which is too much.
Is there any way to hint the browser to do the scaling first then make the page visible? The older version of chrome was doing it right. I can make the page visible after 600 ms using setTimeout function but doesn't seem what I want.
CSS
will-change: transform;
Tried this but it has bad effect like blurry text on my content. I don't know why it's pushing the browser to it's limit sometimes, maybe I can better optimize my page but these browsers should be more powerful (safari is the worst - can even render the webpage)
This is the home page
https://elomymelo.com/
You should see big page fitting inside the screen and it'll probable take 200 ms pretty fast
proportional resize on window also works
This is a heavy article page
https://elomymelo.com/oneplus%20nord%20review.html
I tried to hide the scaling effect in this page but not satisfied because browsers mess up sometimes. I need the javascript scaling done much faster like visitors will not see that weird transition.
Call me crazy, but I'm working on a game using vanilla DOM and TypeScript. It's not action-heavy, but there are some animations going on, which are driven from JavaScript (too complex to do in CSS).
I'm already applying the common trick of translateZ(0) (called null transform hack or less accurately silver bullet) to pull animated elements into their own rendering layer, and I'm animating nothing besides compositor-only properties (transform and opacity). This works beautifully: during the game, everything feels buttery smooth, even on older mobile devices.
The problem is during the start of the game. At that moment, about 70 individually transformed and animated elements enter the page one by one over the space of a few seconds, by animating their opacity from 0 to nonzero. This is causing visible stutter during the animation.
My guess was that Chrome is being too clever here, and will only rasterize each element at the moment it first becomes visible. A quick check with the dev tools confirms this, as there's a lot of rasterization going on even during the animation:
I would prefer to rasterize all these elements once, before the animation starts, and only then trigger the animation. But how can I force rasterization of elements that aren't yet visible, without showing a flash of them to the user?
I'd be happy with a Chrome-only approach, but cross-browser would be even better.
I am currently working on a JavaScript(pure js) based game. The game contains 5 large sprite sheets(e.g. 2861 × 768 and 4096 × 4864). When the game starts, all 5 sprite sheets are preloaded to canvas elements. Three of those 5 sprites represent together one animation, where each sprite contains 75 frames. When one sprite ends with its animation, I hide it and display the next sprite. When the second sprite finishes animating, I hide it and display the third/last one.
When the second or third sprite is about to be displayed, a small delay of 0.5 s - 1 s happens. The image is being decoded.
It is not something that happens just the first time, it is something that happens always. And that animation repeats every 5 minutes, and the small delay happens always.
The reason why I'm using canvas elements for preloading is that I thought WebKit would just throw away decoded images for some time being unused and that the canvas element would prevent WebKit from deleting it from memory. But that does not work.
I've tried almost every optimization I'm aware of. I have even refactored all my CSS by removing descendant selectors etc.
The renderer I'm using to draw those animations is built by myself and it is working perfect, so that could not be the problem, since it is working very well in Firefox.
EDIT [2016/03/04]:
I made a mode with canvas and the result is even worse. It laggs a lot. And the delay remains the same. Only in NW, the problem does not persist in Chrome neither in Firefox.
Canvas mode - Lags:
Default(HTML) mode - Works perfect:
Codepen: My renderer http://codepen.io/anon/pen/JXPWXX
Note: If i hide those other elements with opacity:0.2 rather than opacity:0, the problem does not happen. But, I can not hide them like that since they remain still visible. They shouldn't be visible. If I add opacity:0.01 it is not visible and the problem does not happen in Chrome, but still persists in NW.
In NW, when I swtich from opacity:0.2 to opacity:1, an image decode is being processed. The same thing does not happen in Chrome browser.
I am using the following version:
nw.js v0.12.3
io.js v1.2.0
Chromium 41.0.2272.76
commit hash: 591068b-b48a69e-27b6800-459755a-2bdc251-1764a45
The three image sprites are 14.4MB, 14.9MB and 15.5MB size. Each sprite contains 75 frames.
Why could this be happening and how can I prevent it?
Try to switch to google-chrome directly since the new nw version is probably released 19.04.2016. After that NW will hopefully keep up with every Chromium release.
You should not have the same problems in Chrome.
Given that keeping Webkit thinking the image is still displayed makes the problem disappear (as your opacity experiment shows), I'd move it nearly completely out of the visible area, with only a single transparent row overlapping with the viewport (using overflow hidden).
Note that an unpacked 4000x4000 sprite sheet will use 64 Megabytes of RAM (4 bytes (=RGBA) per pixel), so perhaps it might be better to make sure the next image gets "warmed up" a bit ahead of time, without keeping all of them unpacked all the time?
I'd recommend using idata = ctx.getImageData(0, 0, canvas.width, canvas.height) to retrieve the data array from the canvases, then ctx.putImageData(idata, 0, 0) to switch between sprites, rather than hiding the canvases.
I'm currently working on a small canvas game written in pure javascript from scratch.
The game involves a 2d lighting algorithm similar to this one, but with one light source and 25 polygons which makes for about 30,000 calculations per frame.
My frame rate is great in Safari, meh in Chrome, and unplayable in Firefox. However, if I have the Chrome developer console up while playing the game, the frame rate is the same as Safari.
What could be the reason for this?
After the comments suggested the window size might be affecting the frame rate, I found out that the smaller the window, the smoother the game runs but only in chrome. The amount that is drawn on screen or any calculations used by the game don't depend at all on the screen size.
I measure the frame rate difference purely by eye, and you can see the effect in these gifs:
Bad, big window:
Good, small window:
The game runs much smoother in the browser than is apparent in these gifs, but the effect is still noticeable.
I can get the same effect to happen with the first example in the link that I posted. Is it just me or does anyone else get the same effect?
Even stranger... I gotten the same effect on several other websites, like Facebook when I scroll the home feed. The bigger the window, the choppier the scrolling gets. Is this a Chrome specific thing, is anyone getting similar results?
I've seen this as well in my pages/applications. The issue seems to apply to anything, but is more pronounced with canvas and accelerated CSS. As far as I can tell, this issue is a performance bug relating to Chrome's composited layer rendering. Basically, Chrome breaks the page up into layers and uses the GPU to render those layers. You can see these by enabling the "Show composited layer borders" option in the "Rendering" tab on the dev console. Chrome's FPS performance decreases as the number of composite layers increases, regardless of the layers changing or not.
Here's an independent example. Steps to reproduce:
Load this page in Chrome, it's a relatively simple animated CSS demo that is a fixed size like your game: http://www.subcide.com/experiments/fail-whale/
Bring up the Chrome developer window (pop it out so it's an independent window) and enable the "Show FPS meter" option.
Size the window small so that it just contains the fail whale demo. Note your FPS.
Now size the window large or full screen it. Note your FPS.
With a small window, I get 55 FPS. Full screen, I get 34 FPS. I would expect the FPS to be nearly the same, regardless of the page size as the animated area doesn't change. The FPS seems to be proportional to the number of composite layers on the visible screen. Also, resizing the window results in the animation being chunky and skipping frames. If I perform the same window resizing in Safari, the animation stays smooth. Safari knows there's nothing new to render, while Chrome is seemingly doing a bunch of work for no reason.
So the reason why you see better performance when your dev console is open is because you have your dev console inline/embedded with the page, which makes the page itself smaller when it's open. This results in a page with fewer composite layers for Chrome to handle, which results in better FPS. If you pop your developer console out so it's an independent window and doesn't affect the page size, your FPS won't be affected by the dev console being up or not.
This appears to be the "why" this is happening. Now, if anyone figures out what can be done about this, I'd certainly be interested to know.
I made a game where you can walk on a 2d grid world (Pokémon style) and currently you just hop from tile to tile instead of a nice walking animation in between.
I'm right now working on that walking animation, and it all works, except that the browser doesn't reflow/repaints fast enough.
If I closely zoom in on the sprite I can see the sprite moving and doing only half of the replaces he needs to do. This creates a lag feeling, which I obviously not want. So I googled today and learned about reflow and repaints and that the browsers stacks the animations until a certain time and then executes them in batches.
I want to avoid the stacking of animations so I searched on Google, and found a lot of hacks, which are not working for me, unfortunately...
I used hacks like requesting the offsetTop, hiding and showing the element, and some others which are easily to be found online. None of them worked.
I then learned here: http://dev.opera.com/articles/view/efficient-javascript/?page=3#reflow that the browser may reflow in the background, without making it visible. (probably why the hacks weren't working)
Do you have any way so I can make the browser visibly reflow?