requestAnimationFrame called right before the end of the frame?
Reported by
stac...@gmail.com,
Apr 28 2016
|
||||||||||||||||
Issue descriptionUserAgent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36 Steps to reproduce the problem: 1. Open the attached page. 2. Once the page loads and starts animating, record a few seconds of timeline in the developer tools. What is the expected behavior? Smooth animation, also when updating the contents of the canvas. requestAnimationFrame() callback called at a time that gives the full 16ms to render the frame. What went wrong? Animation is choppy when canvas contents is updated. requestAnimationFrame() callback is called right before the end of the frame, which makes impossible to make any meaningful work (such as update canvas content) and stay in the 60fps animation zone (see the attached timeline). Did this work before? N/A Chrome version: 50.0.2661.87 Channel: n/a OS Version: 10.0 Flash Version: Shockwave Flash 21.0 r0 This might be a similar issue to: https://bugs.chromium.org/p/chromium/issues/detail?id=604365. I'm also seeing the same behaviour on Mac Os, Chrome 50.0.2661.86.
,
May 1 2016
,
May 1 2016
,
May 1 2016
,
May 2 2016
Unable to reproduce the issue on Windows 7, Mac 10.10.5, Ubuntu 14.04 using 50.0.2661.87, latest stable 50.0.2661.94, canary 52.0.2721.0 with below steps: 1.Opened timeline.html in chrome and navigated to dev tools->timeline tab. 2.Enabled 'Show FPS meter' and started recording. 3.Observed the smooth animation with FPS rate: 60.0 fps. Please find attached screencast and update if anything missed here in triaging the issue. stachoo@Could you please check the issue on latest chrome versions and update the thread with screencast if issue still persists.
,
May 2 2016
To see the issue you'd need to zoom-in in the timeline to the moments where long frames occur (see the recording attached, this time with the latest Chromium from https://download-chromium.appspot.com/, 52.0.2723.0). The issue is that rAF callback seems to be called right before the end of the frame, so if the callback takes more than, say, 1ms to execute, this causes long frames. In the attached example code, the execution of rAF callback is capped at 12ms, so in theory there should be no long frames indicated on the timeline.
,
May 2 2016
Also attaching the raw time line corresponding to the screencast I attached. Once again, the issue is not about continued periods of <60 fps animation, but about the fact that rAF callback scheduling makes it impossible to do more than 1-3ms worth of work without dropping frames (long frames).
,
May 2 2016
Here's a better way to show the problem. There are two code examples attached: timeline-periodic-redrawing.html timeline-continuous-redrawing.html The only difference between them is that *-continuous-redrawing.html redraws the canvas every frame, while *-periodic-redrawing.html redraws the canvas once every 100 frames. In both cases the redraw time is capped at 8ms, they do exactly the same work. With continuous redrawing there are no long frames at all, while with periodic redrawing, each canvas redraw (done every 100 frames) causes a long frame. I'm not sure how rAF callbacks are scheduled -- maybe there's some kind of prediction going on that gets fooled by the 99 quick-to-execute callbacks and assumes the 100th callback will also execute quickly and the much-longer-than-predicted (but still well within the frame budget) execution time is the cause of long frames?
,
May 3 2016
Tested the issue on Windows 7 using 50.0.2638.0(good build for Issue 604365 , latest canary 52.0.2623.0 with below steps: 1.Opened timeline-periodic-redrawing.html and navigated to dev tools->timeline tab. 2.Recorded for few seconds. 3.Observed the fps frame rate as in attached screenshots. ccing 'sunnyps@' from reference attached bug. sunnyps@Could you please check the screenshots and confirm if this is same as ' Issue 604365 '.
,
May 3 2016
,
May 8 2016
Here's another more spectacular example, but I'm not sure if this is the same underlying issue. The attached example code does this: * there are two canvases with static (non-changing) content, * in every rAF callback we alter the transform CSS property of both canvases, just as in the previous examples, * each canvas has CSS-transitioned opacity, * once every 200 rAF callbacks we switch the opacities of the canvases (one becomes opaque, the other becomes fully transparent). The latest Firefox, IE and Edge display silky-smooth animation, while Chrome (I checked latest stable Chrome and 52.0.2729.0) show terrible jank when opacities are transitioned. I also attach some short timeline data saved from Chrome 52.0.2729.0.
,
May 10 2016
sunnyps@Could you please look into this issue and update as per comment #9?
,
May 26 2016
Removing Blink>Animation label since this is a scheduling issue. The animation team member is in CC list.
,
May 31 2016
+ brianderson@
,
Jul 11 2016
Any news or update? I still have the issue on chrome 51, on chrome 54 it works fine.
,
Jul 21 2016
I've just checked 54.0.2803.0 canary (64-bit) and the issue shown in Comment 11 (https://bugs.chromium.org/p/chromium/issues/detail?id=607650#c11) seems to be gone. However, rAF callback is still called towards the end of the frame making it impossible to do any meaningful work in the main thread without dropping frames (as shown in timelines from Comment 9, https://bugs.chromium.org/p/chromium/issues/detail?id=607650#c9).
,
Jan 11 2017
Do the frame markings on the timeline view really show the video synchronization timing? If not, it would be most confusing and the issue may even not really be what we are thinking. The rAF callback should get called always right AFTER the video synch (vertical retrace), that is, at the beginning of the next "frame" time window, so it has the most available time to process.
,
Feb 19 2017
I just found this issue after I filed issue 693898 -- please dup that issue into this issue. The bottom line: 'frame' info in Dev Tools is broken. The frame location and frame durations are 100% wrong (stac...@gmail.com, no rAF is NOT called before the end of the frame) -- and it is crazy easy to prove this ( issue 693898 ). It seems like all the logic is already there in DevTools to deal with frames -- so hopefully the 'fix' is just using the correct begin frame time (instead of the incorrect time is currently uses)? sunnyps, can this be fixed ASAP, without significant resources?
,
Feb 19 2017
A new test... Visit vsynctester.com, click on the gear icon, check "Even frame pre-delay" and set to a ms of 8. vsynctester.com shows that frames are still being produced at the same Hz (successfully), and are still fully synchronized to the display (vsync indicator stays 'gray'). Then capture a DevTools timeline and notice that frame location and duration are all wrong (attached).
,
Feb 20 2017
,
Feb 21 2017
sunnyps: The bug is that the F12 timeline ignores the "BeginMainThreadFrame", and considers the 'end' of the prior frame as the beginning of the next frame. Will this be fixed?
,
Feb 21 2017
sunnyps: Found the bug. BeginFrame is incorrectly ignored in TimelineFrameModel.js. The startTime of the DrawFrame is used instead of the startTime of the BeginFrame. The fix: In handleDrawFrame(), change "this._startFrame(startTime)" to "this._startFrame(lastBeginFrame||startTime)", and add a "var lastBeginFrame = this._lastBeginFrame" near the top of that function.
,
Feb 21 2017
Re #23 -- This behavior is by design -- basically, from the user point of view the frame happens when the pixels hit the screen, so we try to be as close as possible to that point. The BeginFrame is just internal to the compositor logic, so I don't think it's meaningful to expose it most of the time (though you can see it if you enable "Show all events on Timeline" experiment). The rendering pipeline is multithreaded and asynchronous, so one frame on main thread can possibly be started before rendering of another frame is complete, so there's nothing wrong with that per se.
,
Feb 21 2017
,
Feb 21 2017
caseq: Then remove all frame duration coloring and all 'long frame' indications -- see comment #20 -- as those are then wrong.
,
Feb 21 2017
caseq: actually, can we get a line on the 'vsync' location?
,
Feb 21 2017
caseq: You said, "the frame happens when the pixels hit the screen". OK. So why is the timeline showing frames times of 6.7ms 26.9ms, 6.9ms, 26.0ms, 7.2ms, 27.2ms -- when the bits are hitting the screen every 16.721ms on my notebook (that is when ANGLE Present()'s the bits)?
,
Feb 21 2017
Ok, re-opening since I guess the current instrumentation is not quite accurate -- it used to be better when the swap buffers was issued by the renderer, but now with the browser compositor sending it there would be a considerable discrepancy I guess. We need to bring it closer to actual swap buffers in the uber-compositor.
,
Feb 23 2017
caseq, isn't Chrome supposed to be presenting frames on vsync on all platforms? If so, maybe the timeline should be showing timing of display frames (vsync). What do you think?
,
May 6 2017
,
Oct 5 2017
Bulk DevTools triage, closing low priority issues with no action plan.
,
Oct 5 2017
,
Dec 18
Bulk DevTools triage, closing low priority issues with no action plan. |
||||||||||||||||
►
Sign in to add a comment |
||||||||||||||||
Comment 1 by yutak@chromium.org
, Apr 29 2016