Re: setImmediate usage on the web

On 24 June 2015 at 23:42, Tobin Titus <tobint@microsoft.com> wrote:

> Ross, with regards to requestIdleCallback
> <https://docs.google.com/document/d/1ZgYOBi_39-N6AbjL99qesiDagaSTbpN0R6CrSVK8NE4/edit#heading=h.lobhanl56igp>,
> I’m happy to be corrected, but I feel like requestIdleCallback is
> setImmediate with an “best guess” at the idle time provided to the
> callback.  Apart from telling the callback how long they have to run, I’m
> not sure how they differ. With 5% usage on the web of setImmediate, it
> would be hard to abandon it and hard to understand why other browsers
> haven’t implemented the existing spec. We add features to the platform all
> the time and I get that. But this feels like an opportunity to extend the
> existing API rather than starting from scratch.
>

No I don't think this is the case. There are a number of differences
between requestIdleCallback and setImmediate over and above the deadline
argument.

One difference is that a requestIdleCallback registered during an idle
period doesn't become eligible to be run until the next idle period. This
allows code patterns like the following:

  function checkSpelling(deadline) {
    if (performance.now() + 5 <= deadline.deadline) {
      // This will take more than 5ms so wait until we
      // get called back with a long enough deadline.
      requestIdleCallback(checkSpelling);
      return;
    }
    // do work...
  }

If this is called with a deadline of less than 5ms then it won't get run
again until the next idle period, at which point the deadline may be large
enough to do the work. If the same pattern was used with setImmediate then
the callback would get to run again immediately with the same (or a
slightly smaller) deadline each time until the deadline is finally used up,
causing the CPU to burn power unnecessarily.

The second major difference is that requestIdleCallback is lower priority
than any other work, where as far as I can tell, setImmediate is only lower
priority than internal rendering operations. You can see this in two
(contrived) examples I've experimented with.

One code snippet [1] has a rAF callback which uses up the full 16.67ms
frame budget each rAF, and another callback scheduled using either
requestIdleCallback or setImmediate. When using requestIdleCallback (with
the prototype Chrome implementation here
<https://codereview.chromium.org/1119683003/>) only "raf" will be printed
to the console - the requestIdleCallback never gets a chance to run because
the is no idle time available. When setImmediate is used instead (tested on
IE12 since I don't have access to a Windows 10 machine to test on MS Edge)
the console shows "raf, idle, raf, idle..." - even although there is no
idle time available the setImmediate callback still gets a chance to run.

The same is true for a page which uses up all CPU time during setTimeouts
[2] - when scheduling another callback via requestIdleFrame you get only
"timeout" printed in the log because the timeouts are using up all idle
time, however when setImmediate is used to schedule the callback you get
"timeout, idle, timeout, idle..." - with the setTimeout callback seeming to
get a chance to run at each turn of the even loop, whether the browser is
idle or not.

It would be possible to modify setImmediate to have a similar processing
model, such that the callbacks only happen if the browser is truly idle,
however I feel that this would cause a lot of confusion to existing users
who would wonder why their callback doesn't run "immediately" (particularly
given the name). In addition, making such a change would probably requires
something like requestIdleCallback's optional "timeout" parameter, so that
authors could guarantee that a callback gets run at some point even if the
browser is never idle during the time period.

I'm sure there are many valid use-cases for setImmediate (in particular
avoiding the clamping to 1ms of setTimeout(, 0)), however I think there are
an important set of use cases which would be better served by a new API
which is purely focused on enabling background work while the browser is
idle.

Cheers,
Ross

[1] https://github.com/rmcilroy/rIC_tests/blob/master/raf.html
[2] https://github.com/rmcilroy/rIC_tests/blob/master/setTimeout.html

Received on Thursday, 25 June 2015 14:15:57 UTC