Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use RAF's timestamp for smoother animations #3143

Open
joliss opened this issue Jun 6, 2016 · 18 comments · May be fixed by #3151
Open

Use RAF's timestamp for smoother animations #3143

joliss opened this issue Jun 6, 2016 · 18 comments · May be fixed by #3151
Assignees
Milestone

Comments

@joliss
Copy link

joliss commented Jun 6, 2016

jQuery 3.0.0-rc1 uses requestAnimationFrame, resulting in significantly smoother animations compared to before. However, its tweening logic uses Date.now() instead of the RAF timestamp argument. As a result, the animation is still slightly choppy.

Before you switch to using timestamp, I should point out that the Velocity.js library opts not to use timestamp (velocity.js:3366):

/* We ignore RAF's high resolution timestamp since it can be significantly offset
   when the browser is
   under high stress; we opt for choppiness over allowing the browser to drop huge
   chunks of frames. */
var timeCurrent = (new Date).getTime();

I don't know if this is actually still an issue in modern browsers. @julianshapiro originally wrote this code in 2014 -- perhaps he can chime in with some details.

I created a test case to demonstrate choppiness resulting from not using timestamp: https://codepen.io/joliss/pen/wWKGeV/ (The test case uses Velocity.js, but I believe it's the same for jQuery.)

My hope is that you can use this test case as a debugging aid, and as a motivating example to convince browser vendors to get any remaining timestamp issues resolved.

Running the CodePen, we see that there is some slight choppiness with the jQuery's getTime implementation:

a pen by jo liss jtbyc

Using the RAF timestamp argument instead, the animation feels smoother, and the graph is perfectly smooth as well:

a pen by jo liss her4j

I thought that perhaps using the microsecond-resolution performance.now() function would improve smoothness, but it doesn't seem to help much:

a pen by jo liss hft9a

@mgol
Copy link
Member

mgol commented Jun 6, 2016

A great analysis, thanks a lot! I'm surprised that using performance.now() gives worse results than using the timestamp since it's based on the same timer.

I made a quick patch for jQuery 3.0.0-rc1 that made it use the rAF timestamp:
https://gist.github.com/mgol/59155e734d86095f58d505824f7503c2
and added a button for it in your test case:
http://codepen.io/mgol/pen/VjvjdL

The graph looks similar to the Velocity using timestamp one.

Note that I'm seeing the performance difference in Chrome 51 but I don't see any gain in Safari (9.1 & TP) and Firefox; Safari mostly looks like your "Velocity plus performance.now" test case in all cases (including the getTime one in which it's better than Chrome), Firefox looks terrible in all cases. I'm not sure if doing sth like that just for Chrome is worth it... :/

EDIT: In Edge 13 all cases look the same, worse than in Safari but way better than in Firefox.

@mgol
Copy link
Member

mgol commented Jun 6, 2016

Re Firefox: the terrible graphs that I'm seeing are there only if I use the integrated graphics card in my MacBook. i.e. Intel Iris Pro 1536 MB. If I switch to the dedicated AMD Radeon R9 M370X 2048 MB, it gets closer to Safari. Perhaps Firefox has problems with hardware acceleration for Intel GPUs.

@julianshapiro
Copy link

julianshapiro commented Jun 6, 2016

I've always found that dropping a huge chunk of frames upfront is more visually jarring than an FPS hit. In real world (low-stress) animation scenarios, the FPS hit isn't that noticeable — if at all.

@joliss
Copy link
Author

joliss commented Jun 6, 2016

@mgol Good point. I created an issue on the Firefox bug tracker: https://bugzilla.mozilla.org/show_bug.cgi?id=1278408 Let's see what they say, and if necessary we can create issues on Edge and Safari too.

@julianshapiro I agree dropping chunks of frames is really bad. Is this still happening though? (Or to be more precise, is it worse for timestamp compared to Date.now()?) Plotting timestamp values with a no-op requestAnimationFrame, I don't see any initial framedrops: https://codepen.io/joliss/pen/ZObOPm

@timmywil
Copy link
Member

timmywil commented Jun 7, 2016

Very cool. Thanks for this.

@digitarald
Copy link

I also updated the bug with a reference to an older bug on which I added @bzbarsky to take a deeper look.

@markelog
Copy link
Member

markelog commented Jun 8, 2016

Nice test!

Judging by the discussion in mozilla thread we still can't use it right? After it will be fixed (fingers crossed), we still should look at older/other browsers that we support?

@dmethvin
Copy link
Member

dmethvin commented Jun 8, 2016

On Firefox 46 with Windows 10 it looks as smooth as Chrome. As long as we don't make things much worse on Firefox by changing to the rAF timestamp is there anything to stop us from changing it now? To @markelog's point we would also need to ensure it doesn't degrade too much for browsers like Android or IE9.

@mgol
Copy link
Member

mgol commented Jun 8, 2016

@dmethvin My quick patch made jQuery.fx.tick accept a timestamp parameter so that'd slightly change the API; to avoid that we'd need a wrapper function which might increase the code size a little.

I just don't see much gain in using the timestamp until it improves the situation only in Chrome. Maybe as a way of preparing for the future? I can prepare a PR to discuss the details further.

@mgol
Copy link
Member

mgol commented Jun 8, 2016

Ah, you said it's as smooth as Chrome for you in Firefox on Windows 10. Do you mean it looks like the same graph as the second one from the original @joliss post, completely smooth? That'd change the situation. :)

@dmethvin
Copy link
Member

dmethvin commented Jun 8, 2016

Yeah, here are my Firefox results, very smooth:
capture

@markelog
Copy link
Member

markelog commented Jun 8, 2016

In here @mgol points out that timestamp dependant on graphics card (@dmethvin your card might just be in "good" category), is it not case? The same story could be with other browsers?

This https://bugzilla.mozilla.org/show_bug.cgi?id=1278408#c10 is also disturbing

@markelog
Copy link
Member

markelog commented Jun 8, 2016

Also, if we can do this and it is not the issue, why those tickets are open?

@mgol
Copy link
Member

mgol commented Jun 8, 2016

In here @mgol points out that timestamp dependant on graphics card (@dmethvin your card might just be in "good" category), is it not case?

Possible. The current data points to the thesis that it's never worse when using the timestamp than when not using it and sometimes it's better.

mgol added a commit to mgol/jquery that referenced this issue Jun 8, 2016
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Fixes jquerygh-3143
@mgol mgol linked a pull request Jun 8, 2016 that will close this issue
6 tasks
@mgol
Copy link
Member

mgol commented Jun 8, 2016

PR: #3151. Please review.

mgol added a commit to mgol/jquery that referenced this issue Jun 8, 2016
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Fixes jquerygh-3143
@mgol
Copy link
Member

mgol commented Jun 22, 2016

CC’ing Mozilla folks: @miketaylr @digitarald @bzbarsky @annevk @kentuckyfriedtakahe @cyberdees

@timmywil timmywil added this to the 3.2.0 milestone Jun 30, 2016
mgol added a commit to mgol/jquery that referenced this issue Jul 6, 2016
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Fixes jquerygh-3143
mgol added a commit to mgol/jquery that referenced this issue Jul 7, 2016
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Fixes jquerygh-3143
mgol added a commit to mgol/jquery that referenced this issue Aug 8, 2016
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Fixes jquerygh-3143
mgol added a commit to mgol/jquery that referenced this issue Mar 9, 2017
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Mar 9, 2017
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
@mgol mgol modified the milestones: 3.2.0, 3.3.0 Mar 15, 2017
@mgol
Copy link
Member

mgol commented Mar 15, 2017

Pushing to at least 3.3.0 as Chrome apparently has a bug that makes timestamps arrive to our step function not always in ascending order. See #3151 (comment) for more details.

@timmywil timmywil modified the milestones: 3.4.0, 3.3.0 Jul 24, 2017
mgol added a commit to mgol/jquery that referenced this issue Oct 12, 2017
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
@timmywil timmywil changed the title We should use RAF's timestamp for smoother animations Use RAF's timestamp for smoother animations Sep 17, 2018
@mgol
Copy link
Member

mgol commented Oct 3, 2018

This requires more investigation, with issues around out-of-order scheduling in Chrome that I've experienced as well as recent timer throttling due to Spectre. Postponing to 4.0.0.

@mgol mgol modified the milestones: 3.4.0, 4.0.0 Oct 3, 2018
mgol added a commit to mgol/jquery that referenced this issue Jan 17, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Mar 4, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Mar 11, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Apr 17, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Apr 23, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Apr 23, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Apr 29, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Apr 30, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
mgol added a commit to mgol/jquery that referenced this issue Aug 30, 2019
In some environments that support the requestAnimationFrame timestamp callback
parameter using it results in smoother animations.

Note: the rAF timestamp is using the same API as performance.now() under the
hood so they're compatible with each other. However, some browsers support rAF
(with a timestamp parameter) but not performance.now() so using them both
would introduce an error. This commit stops using rAF in browsers that don't
support performance.now(). From all the browsers jQuery supports this only
affects iOS <9 (currently less than 5% of all iOS users) which will now not
use rAF.

Fixes jquerygh-3143
Closes jquerygh-3151
@timmywil timmywil modified the milestones: 4.0.0, 3.7.0 Aug 26, 2022
@timmywil timmywil modified the milestones: 3.7.0, 4.1.0 Feb 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

7 participants