Shall the requestAnimationFrame calls always be throttled down to 60 FPS? - javascript

requestAnimationFrame is called whenever the screen is ready for a repaint.
On modern screens the refresh rate may be a lot higher then 60 frames per second. If there is a lot of stuff going on inside those calls - it may impact the overall performance of the application.
So my question is: shall the requestAnimationFrame always be throttled down to 60FPS? Can human eye actually tell the difference between for example a 16ms and an 8ms repaint delay?
[UPDATE]
I ended up throttling it down to 60FPS for higher performance on screens with high refresh rate.
And would suggest this approach to everyone who has a lot of stuff goin on inside the rAF calls.
You should do your own testing of course though.

Per MDN it will not necessarily always be 60 FPS.
Relevant quote:
This will request that your animation function be called before the browser performs the next repaint. The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation. The callback rate may be reduced to a lower rate when running in background tabs.
As for can the human eye distinguish 60 vs 120 FPS, well, that's an open, and opinionated question. Some claim to see it, other's claim its impossible. Allowing the end user to choose is (or simply using their hardware to its fullest) probably best.
As markE's comment pointed out. The requestAnimationFrame callback receives a DOMHighResTimeStamp which is a high precision timer accurate to the "thousandth of a millisecond." By using this time-stamp, and calculating the delta between frames, you can tune your refresh rate to whatever desired value.
References:
requestAnimationFrame
W3C Timing control for script-based animations
DOMHighResTimeStamp
Note: please remember to leave a comment addressing any downvotes, otherwise they are not useful feedback.

I guess that people having 120hz or higher frame rate displays are aware that it requires more resources to generate twice as much frames.
That and/or they have more powerful computers than most users. I personally have a very powerful PC but two 60hz displays and the only guy I know that has a display with a higher framerate than 60hz is a pro gamer so obviously he has no performance issue when browsing the web.
Also, people using very high framerate displays are getting used to that level of fluidity and they might notice the difference (event if I doubt it).
My two cents are : respect their preference of having an overkill display. It's what they want.

By default, i think it is good to limit the framerate to 60Hz, since :
• High framerate means more heat, so the (cpu) fan noise will be annoying.
• For most game nobody will notice.
• it's easy to do.
• For those with ecological concerns, high fps uses more power (==> more CO2).
About the visual interest of 120 Hz :
For 2D games where only a tiny amount of the screen is actually changed between each frame it's of little to no interest.
For 3D games, especially those targeting to be realistic, using 120Hz allows to get a more 'cinema'-like experience.
Why ?
==> Most 3D renderers only render a scene at a point in time, so what you see is a succession of 'perfect' still images.
On the other hand, a real camera will -like the human eye- be kept open for a few milliseconds, thus the moves happening during this time will leave a trail on the image, providing a more true to life experience.
The 60Hz boundary is only enough to fool the eye about the motion, so what the 120Hz+ screen brings is that the screen is so fast eye remanence cannot follow and you have again that camera/eye trail effect.
The code looks like :
var minFrame = 13;
var maxFrame = 19;
var typicalFrame = 16;
var gameTime = 0;
var lastDrawTime = -1;
animate(drawTime) {
requestAnimationFrame(animate);
var dt = drawTime - lastDrawTime;
lastDrawTime = drawTime ;
if (dt<minFrame) return;
if (dt>maxFrame) dt=typicalFrame; // in case of a tab-out
gameTime+=dt;
// ...
}
function lauchAnimation() {
requestAnimationFrame ( function(t) { lastDrawTime = t;
requestAnimationFrame(animate); } );
}
Rq1 : When you limit the fps, you must take care of the fact that the frame rate is not stable at all in a Browser.
So even with an application doing nothing, on a 60Hz screen, has frame duration that can go from 14ms to 19ms. (!!!!) So you must take some margin when capping the frame rate to some value.
Rq2 : In the example above 'typicalFrame' is to be replaced by the native screen frame rate (that you have to compute by yourself).

Related

Slow down world time and rendering in Javascript for Webkit / Chrome

I would like to record browser animations in the smoothest possible framerate, including an alpha channel. Due to single threaded performance limitations I am looking for a way to slow down the producer of these animations. I currently achieve this by increasing the delay and duration of timers (in my case anime.js), this allows me to sample screen at a lower frame rate, while the target frame rate can be achieved.
The change of duration and delays is not overly painful, but I would like to do this in a more generic way. For example instruct the browser to have a world clock that runs on 10% of real speed. I have already found the Proxy suggestion below, but this does not seem to impact the current animation rendering.
Slow down time with JavaScript
What can be done to globally reduce all the animation, as if everything would take 10 times longer?

RequestAnimationFrame behaviour..hows it work?

I have been playing around with requestAnimationframe for chrome, and wondered how it actually behaves.
When i load my canvas and draw, I get a steady 60FPS. If i scroll around using offset like a click and drag around a map, the FPS will drop (as expected)...once i stop dragging around the map, the FPS creeps back up to its steady 60fps, again as expected.
Here how ever is where I'm wondered if this is delibrate for requestAnimationframe. If i drag the map around until the FPS drop, drops below 30 for an extended period of time, once i stop dragging, it climbs back up, but this time it hits 30FPS and will not go higher. It appears as if the browser decided 30FPS is perhaps the best option.
Is this delibrately done by the browser, i been trying to find out if this is the case. Because it will go to 60fps if i dont drop below 30fps for too long.
Yes, it's something that the browsers are capable of doing.
"How it's supposed to work" isn't really something that anybody can answer, here.
The reason for that is simply that under the hood is 100% browser-specific.
But it's very safe to say that yes, the browser is capable of deciding when you should be locked into a 30Hz refresh, rather than a 60Hz refresh.
An illustration of why this is the case:
requestAnimationFrame() is also tied into the Page Visibility API if the vendors want (very true for Chrome).
Basically, if the page isn't visible, they can slow the requestAnimationFrame() updates down to a few times per second or pause them altogether.
Given that knowledge, it's entirely plausible to believe that one of two things is happening:
they're intentionally capping you at 30fps, because they feel your experience will be more stable there, based on averaged performance data
they're intentionally throttling you, but there's some bug in the system (or some less than lenient math) which is preventing you from going back up to 60, after the coast has cleared, .and if they are using averaged performance data, then that might be part of the issue.
Either way, it is at very least mostly-intentional, with the only unanswered question being why it sticks to 30fps.
Did you leave it alone for 20 or 30 minutes after the fact, to see if it went back up at any time, afterwards?
You can run Timeframe analysis from Chrome DevTools to look for maverick JS that is slowing down your animation times.
https://developers.google.com/chrome-developer-tools/docs/timeline
RAF will find the best place to paint your changes not the closest one. So, if the JS in the RAF callback is taking two frames worth of time(around 16ms per frame on your 60hz hardware), then you FPS will drop to 30.
From Paul Irish via Boris
Actually, “It’s currently capped at 1000/(16 + N) fps, where N is the number of ms it takes your callback to execute. If your callback takes 1000ms to execute, then it’s capped at under 1fps. If your callback takes 1ms to execute, you get about 60fps.” (thx, Boris)
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

How can I recognize slow devices in my website?

When adapting a web page for mobile devices I always rely on css media queries.
Recently I no longer worry only about the screen size, but also the javascript engine of many mobile devices. Some common javascript effects that rely on window scrolls or a quick sequence of DOM transformations work really bad on slow devices.
Is there any way to guess the device performance so I can enable/disable elements that look bad on slow devices?
So far I can only think of bad solutions:
screen size. narrow screen "might" mean slow device
user agent information. I could look at the device, browser or cpu, but that does not seem a stable long term solution because of the amount of devices to consider
UPDATE:
Fixed my question to focus on one problem. In the comments there is a good solution for the touch interface problem.
It certainly seems as though there is no particularly good solution for this issue (which would make sense since this type of stuff is normally supposed to be the type of stuff that's hidden away). I think either way your best starting with UA detection to take care of those platforms that are known to fall into one category or another. Then you'd have 2 options to flexibly adapt to unknown/uncertain platforms:
Progressive Enhancement: Start with a stripped down test and load a small performance test or tests to gauge the device performance and then load the files for the appropriate enhancements. Test such as already provided or at: Skip some code if the computer is slow
Graceful Degradation: Wrap those features that are candidates for causing unfavorable UX on slower devices in a higher order function that replaces them if they take too long on first execution. In this case I'd probably add it to Function.prototype and then allow an acceptable delay argument to be chained on to the function definition. After the first invocation store the time lapsed, and then on the second invocation if the time lapsed is over the delay swap out the function with a fallback. If the time elapsed is acceptable then remove the profiling code by swapping in the standard function. I'd need to sit down and work out sample code (maybe this weekend). This could also be adjusted by additional arguments such as to profile multiple times before swapping.
The first option would likely be the friendlier option, but the 2nd may be less intrusive to existing code. Cookies or collecting further UA data would also help from continuing to profile after information is retrieved.
The only way I could think of would be to run some kind of speed test in JS in the background either before or while using the effects. This should catch devices that are slow due to their processor speed or vice versa, catch devices that are time accurate/fast. However if the devices have optimisations meaning they use different processors to calculate graphical effects, this will not work.
var speedtest = function(){
/// record when we start
var target = new Date().getTime(), count = 0, slow = 0;
/// trigger a set interval to keep a constant eye on things
var iid = setInterval(function(){
/// get where we actually are in time
var actual = new Date().getTime();
/// calculate where we expect time to be
target += 100;
/// 100 value here would need to be tested to find the best sensitivity
if ( (actual - target) > 100 ) {
/// make sure we aren't firing on a one off slow down, wait until this
/// has happened a few times in a row. 5 could be too much / too little.
if ( (++slow) > 5 ) {
/// finally if we are slow, stop the interval
clearInterval(iid);
/// and disable our fancy resource-hogging things
turnOffFancyAnimations();
}
}
else if ( slow > 0 ){
/// decrease slow each time we pass a speedtest
slow--;
}
/// update target to take into account browsers not being exactly accurate
target = actual;
/// use interval of 100, any lower than this might be unreliable
},100);
}
Of course by running this you'll affect the speed of the device as well, so it's not the best solution really. As a rule I tend to disable animations and other superfluous things simply when the screen is small.
One other downside to this method - that I've experience before - is that one certain browsers that implement multi-tabbed environments setIntervals are automatically limited to a certain speed when the tab is not being viewed. This would mean for this browsers tabbing away would automatically downgrade their experience - unless this imposed speed limited could be detected some way.
You could make your own mini benchmark of sorts. Do some demanding calculations and time the result. If it's slower than the device you consider to be slowest supported device then you drop to a less intensive version of your site.
You could also just make an easily accessible link to switch to the more basic site if the user is experiencing performance issues.
Going off screen size is not a good idea. Plenty of modern phones have small screens with fast processors.

Increase FPS in animation in javascript

I'm doing an animation using javascript:
function animate(){
window.setTimeout(function(){
//Do a new frame and recall this function till the animation is finished
}, 1000/FPS);//FPS Default 15 approximately 60FPS
}
animate();
I'm wondering how I can increase the FPS without losing the quality? Using the already built-in css3 is not an option because I have custom-built an animation.
A couple of suggestions:
Do not rely on setTimeout, setInterval, or any other built-in utility for scheduling a function invocation to provide a high degree of accuracy or precision, particularly when you are executing custom rendering code.
Decouple the ideas of frame and time in your mind. Yes an animation is internally a series of frames, but the end result is something that's supposed to appear to move fluidly through time. So instead of drawing frame 'n', scheduling a timeout for 1000/FPS and then assuming that "it's time to draw frame 'n + 1' now", try drawing frame 'n', scheduling a timeout for some very short interval (like 10 ms), and then (when the timeout fires) measuring the actual amount of time elapsed between when the animation started and the current point in time. Then use your elapsed time to decide what frame should be showing at this exact moment in time (which may still be 'n', or 'n + 1', or maybe even 'n + 3' if your rendering code takes very long to execute), and render that frame. Trust me, you'll get smoother, more consistent results that way.
In terms of how to improve the framerate and/or rendering quality once you have a reasonably set-up rendering loop, that is all about optimizing your //Do a new frame code as much as you possibly can.
It's worth knowing a couple of things: FPS above 60 is usually meaningless, as browsers struggle to repaint the screen any quicker than that. And setTimeout is inconsistent. Just because you tell a script to run every 50ms (for example), doesn't mean it will. There's typically a variance of up to 15ms in either direction.
Decent strategies for improving quality would be making use of some sort of easing calculation, syncing the FPS with the browser repaint cycle - some information about this here - and making use of motion blur, etc, to smooth the effect.
Check out http://weblogs.mozillazine.org/roc/archives/2010/11/measuring_fps.html for some Firefox-specific insights.

How to determine the best "framerate" (setInterval delay) to use in a JavaScript animation loop?

When writing a JavaScript animation, you of course make a loop using setInterval (or repeated setTimeout). But what is the best delay to use in the setInterval/setTimeout call(s)?
In the jQuery API page for the .animate() function, the user "fbogner" says:
Just if anyone is interested: Animations are "rendered" using a setInterval with a time out of 13ms. This is quite fast! Chrome's fastest possible interval is about 10ms. All other browsers "sample" at about 20-30ms.
Any idea how jQuery determined to use this specific number?
Started bounty. I'm hoping someone with knowledge of the source code behind Chromium or Firefox can provide some hard facts that might back up the decision of a specific framerate. Or perhaps a list of animations (or frameworks) and their delays. I believe this makes for an interesting opportunity to do a bit of research.
Interesting - I just took the time to look at Google's Pac-Man source to see what they did. They set up an array of possible FPSes (90, 45, 30), start at the first one, and then each frame they check the "slowness" of the frame (amount the frame exceeded its allotted time). If the slowness exceeds 50ms 20 times, the framerate is notched down to the next in the list (90 -> 45, 45 -> 30). It appears that the framerate is never raised back up, presumably because the game is so short-lived that it wouldn't be worth the trouble to code that.
Oh, and the setInterval delay is of course set to 1000 / framerate. They do, in fact, use setInterval and not repeated setTimeouts.
I think this dynamic framerate feature is pretty neat!
I would venture to say that a substantial fraction of web users are using monitors that refresh at 60Hz, which translates to one frame every 16.66ms. So to make the monitor the bottleneck, you need to produce frames faster than 16.66ms.
There are two reasons you would pick a value like 13ms. First, the browser needs a little bit of time to repaint the screen (in my experience, never less than 1ms). Which puts you at, say, updating every 15ms, which happens to be a very interesting number - the standard timer resolution on Windows is 15ms (see John Resig's blog post). I suspect that an well-written 15ms animation looks very close to the same on a wide variety of browsers/operating systems.
FWIW, fbogner is plain wrong about non-Chrome browsers firing setInterval every 20-30ms. I wrote a test to measure the speed of setInterval firing, and got these numbers:
Chrome - 4ms
Firefox 3.5 - 15ms
IE6 - 15ms
IE8 - 15ms
The pseudo-code for this is this one:
FPS_WANTED = 25
(just a number, it can be changed while executing, or it can be constant)
TIME_OF_DRAWING = 1000/FPS_WANTED
(this is in milliseconds, I believe it is accurate enough)
( should be updated when FPS_WANTED changes)
UntilTheUserLeavesTheDrawingApplication()
{
time1 = getTime();
doAnimation();
time2 = getTime();
animationTime = time2-time1;
if (animationTime > TIME_OF_DRAWING)
{
[the FPS_WANTED cannot be reached]
You can:
1. Decrease the number of FPS to see if a lower framerate can be achieved
2. Do nothing because you want to get all you can from the CPU
}
else
{
[the FPS can be reached - you can decide to]
1. wait(TIME_OF_DRAWING-animationTime) - to keep a constant framerate of FPS_WANTED
2. increase framerate if you want
3. Do nothing because you want to get all you can from the CPU
}
}
Of course there can be variations of this but this is the basic algorithm that is valid in any case of animation.
When doing loops for animations, it's best that you find a balance between the speed of the loop, and how much work needs to be done.
For example, if you want to slide a div across the page within a second so it is a nice effect and timely. You would skip coordinates and have a reasonably fast loop time so the effect is noticeable, but not jumpy.
So it's a trial and error thing (by having to put work, time, and browser capability into account). So it doesn't only look nice on one browser.
The number told by fbogner have been tested.
The browsers throttle the js-activity to a certain degree to be usable every time.
If your javascript would be possible to run every 5msec the browser runtime would have much less cpu time to refresh the rendering or react on user input (clicks) because javascript-execution blocks the browser.
I think the chrome-devs allow you to run your javascript at much shorter intervals than the other browsers because their V8-Javascript-Engine compiles the JavaScript and therefore it runs faster and the browser will noch be blocked as long as with interpreted js-code.
But the engine is not only so much faster to allow shorter intervals the devs have certainly tested which is the best possible shortest interval to allow short intervals and don't blocking the browser for to long
Don't know the reasoning behind jQuery's interval time, as 13ms translates to 80fps which is very fast. The "standard" fps that's used in movies and such is 25fps and is fast enough that human eye won't notice any jittering. 25fps translates to 40ms, so to answer your question: anything below 40ms is enough for an animation.

Categories

Resources