Re: Scheduling multiple types of end-of-(micro)task work

On Thu, Oct 18, 2012 at 4:16 PM, Jonas Sicking <jonas@sicking.cc> wrote:

> On Thu, Oct 18, 2012 at 3:34 PM, James Robinson <jamesr@google.com> wrote:
> > On Thu, Oct 18, 2012 at 3:19 PM, Alan Stearns <stearns@adobe.com> wrote:
> >> On 10/18/12 2:51 PM, "Olli Pettay" <Olli.Pettay@helsinki.fi> wrote:
> >> >On 10/19/2012 12:08 AM, Rafael Weinstein wrote:
> >> >> CSS Regions regionLayoutUpdate brings up an issue I think we need to
> >> >> get ahead of:
> >> >>
> >> >>    https://www.w3.org/Bugs/Public/show_bug.cgi?id=16391
> >> >>
> >> >> For context:
> >> >> --------
> >> >> Mutation Observers are currently spec'd in DOM4
> >> >>
> >> >>      http://dom.spec.whatwg.org/#mutation-observers
> >> >>
> >> >> and delivery timing is defined in HTML
> >> >>
> >> >>
> >>
> >> >> >>
> http://www.whatwg.org/specs/web-apps/current-work/#perform-a-microtask-ch
> >> >>eckpoint
> >> >>
> >> >> The timing here is described as a "microtask checkpoint" and is
> >> >> conceptually "deliver all pending mutation records immediately after
> >> >> any script invocation exits".
> >> >>
> >> >> TC-39 has recently approved Object.observe
> >> >>
> >> >>      http://wiki.ecmascript.org/doku.php?id=harmony:observe
> >> >
> >> >(Not sure how that will work with native objects.)
> >> >
> >> >
> >> >>
> >> >> for inclusion in ECMAScript. It is conceptually modeled on Mutation
> >> >> Observers, and delivers all pending change records immediately
> >> >> *before* the last script stack frame exits.
> >> >>
> >> >> Additionally, although I've seen various discussion of dispatching
> DOM
> >> >> Events with the microtask timing, CSS regionLayoutUpdate is the first
> >> >> I'm aware of to attempt it
> >> >>
> >> >>      http://dev.w3.org/csswg/css3-regions/#region-flow-layout-events
> >> >
> >> >
> >> >Could you explain why microtasks are good for this case?
> >> >I would have expected something bound to animation frame callback
> >> >handling,
> >> >or perhaps just tasks (but before next layout flush or something).
> >>
> >> In the spec bug discussion, it was suggested that we use end-of-task or
> >> end-of-microtask timing. When I looked at these options, it seemed to me
> >> that the regionLayoutUpdate event was somewhat close in intent to
> >> MutationObservers. So between those two options, I picked microtask. If
> >> there's a better place to trigger the event, I'm happy to make a change
> to
> >> the spec.
> >>
> >> The current wording may be wrong for separate reasons anyway. The event
> is
> >> looking for layout changes. For instance, if the geometry of a region in
> >> the region chain is modified, and this causes either (a) overflow in the
> >> last region in the chain or (b) the last region in the chain to become
> >> empty, then we want the event to trigger so that a script can add or
> >> remove regions in the chain to make the content fit correctly. If a task
> >> in the event queue caused the change, then the microtask point after
> that
> >> task is probably too soon to evaluate whether the event needs to fire.
> And
> >> if that was the last task in the queue, then there may not be another
> >> microtask happening after layout has occurred.
> >>
> >> So what I need is an appropriate timing step for responding to layout
> >> changes. Any suggestions?
> >
> >
> > I think events based off of layout are a terrible idea and there is no
> good
> > timing for them.  The regions case is a good example of why not to have
> > them.  If you need javascript to respond to DOM changes then mutation
> > observers are the primitive to use.  If you just want to get callbacks
> at a
> > good time to update visual effects use requestAnimationFrame().
>
> Does that mean that you think events like onresize and onscroll are
> bad? It's an honest question since I can definitely see your argument.
>

onresize when applied to the viewport isn't necessarily bad since it's
talking about something that is input to layout (size of the window) not
output.  Similarly when onscroll is used to detect interactions with the
page and not changing in scroll position due to layout it's not necessarily
evil.  However, both do suffer from the same issues and we've had to apply
various levels of "hacks" to both.

For onscroll, after receiving many bugs we've effectively delayed firing
the scroll event later and later to make sure the callstack is clean and to
try to prevent it from interfering "too much" with the user's interactions.
 In practice, scroll events fire after the user sees the scroll position
update in Chrome in nearly all cases.  For onresize, we've definitely seen
many bugs where people construct infinite loops.  I'm not sure what the
current state of events is with onresize (except that it is inconsistent
between browsers) but if it's firing synchronously or relatively quickly
I'm sure it will be pushed out to fire later and less frequently for the
same reasons as onscroll.


> Though I do wonder if layout events can be useful in cases where you
> don't want to be called every time the DOM changes (MutationObservers)
> or on every time the screen is painted (requestAnimationFrame).
>
> You could use those two, specifically the latter, to replace onscroll
> and onresize. But it might end up using a lot more CPU power if you
> have to check the current scroll position or screen size on every
> painted frame. Likewise it might use a lot more CPU power if you have
> to check layout primitives on every DOM mutation.
>

Indeed. I think the key distinction here is whether the page is trying to
listen to changes that are input to layout (the viewport dimensions
changing, the user providing input leading to scrolling) from changes that
are output of layout.  If a page could reliably listen to the former and
then use requestAnimationFrame to schedule work they could only tick when
they really need to while still reacting.

One complication here is that things that the browser considers internal to
the page like an iframe or div changing size may very well be considered
"external" to the author of a component embedded in a page.  This case is
harder to deal with, but I still feel that the goal should be a directed
flow from things that are inputs to layouts to things that are outputs.

- James


>
> People have been asking for resize events for individual elements for
> a very long time (I think it might even be implemented in some
> non-Gecko browsers). This obviously wouldn't be needed if people used
> MutationObservers and requestAnimationFrame, or MutationObservers and
> page-wide onresize. However it might save a lot of CPU power and make
> authoring a whole lot simpler if you could get called only when it was
> actually needed.
>
> I don't know enough about CSS regions to know if the same thing
> applies there. But I would imagine there are layout changes where
> this applies.
>
> / Jonas
>

Received on Thursday, 18 October 2012 23:42:06 UTC