- From: James Robinson <jamesr@google.com>
- Date: Mon, 2 May 2011 22:30:57 -0700
- To: Boris Zbarsky <bzbarsky@mit.edu>
- Cc: Jonas Sicking <jonas@sicking.cc>, public-web-perf@w3.org, "Robert O'Callahan" <robert@ocallahan.org>
- Message-ID: <BANLkTi=UjBVeHBoBXp4EM_y0RF41itM6Tw@mail.gmail.com>
On Mon, May 2, 2011 at 7:15 PM, Boris Zbarsky <bzbarsky@mit.edu> wrote: > On 5/2/11 10:06 PM, Jonas Sicking wrote: > >> On the other hand, if you do want to implement the feature James is >> talking about here, you'd end up with: >> >> 1) Resample declarative animations. >> 2) Run animation frame callbacks if any. >> 3) Process pending restyles, if any. >> 4) Do relayout, if needed. >> 5) If something with an animationcallback has been moved into the >> screen, goto 2. >> > > Not quite, because if we require that things that are not in the viewport > NOT have their animation frame callbacks called and that animation frame > callbacks are called in order they were set up, then we need to do relayout > before running animation frame callbacks for anything with an element > attached in step 2. In other words, the algorithm would then need to look > like this: > > 1) Resample declarative animations. > 2) While (have animation frame callbacks that might need to run) > I) If next callback has element, flush style and layout > II) Run next callback > 3) Process restyles. > 4) Do relayout. > > or something. I would really like to avoid this situation. That's pretty much exactly what the implementation in WebKit currently does, except that the algorithm operates on a copy of the callback list generated before step 2. In WebKit, style and layout are lazy and ensure they are up to date when nothing has changed is very cheap. This means if the callbacks are 'well-behaved' and do not manipulate styles or layout unnecessarily then the work required by steps 3+4 should be minimal. A callback that does nothing but issue draws targetting a canvas element, for example, should not dirty any style or layout information and so steps 3+4 would just involve checking a few dirty bits in WebKit. Animation callbacks that cause style recalculations or layout to take significant amounts of time are going to be expensive no matter what algorithm we use. One use case motivating this algorithm is that a page may have multiple animations active at the same time that interact with each other, for example the contents of a canvas might be animated by one callback while the canvas itself or some ancestor is moved by another callback. In that case I want to ensure that the canvas contents are always updated when the canvas becomes visible regardless of what order the callbacks are registered in. To put it another way, at the end of the invoke callbacks algorithm there should be no callbacks in the animation frame request callback list that are eligible to run. Since the WebKit implementation copies the list of potential callbacks before invoking any of them, all callbacks registered during the invoke callbacks algorithm are for the next frame and so it is not possible to trigger more than N+1 reflows if there are N callbacks registered at the start of the algorithm. > > Another open question is what happens to unfired callbacks. Do they just get left in the list, or what? Consider a single canvas outside the viewport; in an ideal world we'd be able to do nothing with it until it goes into the viewport (as opposed to waking up every 16.7ms to check whether it might be inside the viewport now). That seems like it imposes a burden on the author, though... > In our implementation callbacks that are unfired due to element visibility checks are left in the list for next frame. In the case of a single animated canvas outside the viewport Chrome will wake up every ~16.7ms, update layout (which is cheap if nothing has changed, remember), check that the element is still not visible, and then do nothing. Ideally we would not do anything until the element became visible but in general I don't think this is feasible. In any case, doing the visibility check in the browser is definitely cheaper than calling into the JavaScript engine and having the script do its own visibility check (which most authors will not do at all). I'm not sure how an author would do better - there is no reasonable way to receive a notification when an element becomes visible that does not involve polling or registering for a large amount of events. - James
Received on Tuesday, 3 May 2011 05:31:32 UTC