FWIW, I just yesterday suggested in #whatwg that the platform should have 
something like IdlePromise or AsyncPromise.
And there is the related spec bug 
https://github.com/whatwg/html/issues/512#issuecomment-171498578


On 05/18/2017 04:22 AM, Mark Hammond wrote:
Given our recent performance push, I thought I'd bring this topic up again.

When writing loops using async functions in browser code, it's still very easy 
to cause jank. For example, a trivial function:

async function janky() {
  for (let i = 0; i < 100000; i++) {
    await Promise.resolve();
  }
}

janky().then(() => console.log("done"));

will cause the browser to hang. While that's not considered a bug in the 
implementation of the promise scheduler, and might not be particularly
surprising in that trivial example, lots of real-world code can still hit this 
case - which both isn't obvious from casual inspection, and even if it
was, doesn't have an obvious solution.

Concretely, we struck this a couple of years ago in bug 1186714 - creating a 
backup of all bookmarks ends up looking alot like the loop above. In
addition, the Sync team is moving away from nested event loops towards 
promises, and our work to date is hitting this problem.

In bug 1186714, we solved the problem by inserting code into the loop that 
looks like:

   if (i % 50 == 0) {
     await new Promise(resolve => {
       Services.tm.dispatchToMainThread(resolve);
     });
   }

http://searchfox.org/mozilla-central/rev/f55349994fdac101d121b11dac769f3f17fbec4b/toolkit/components/places/PlacesUtils.jsm#2022

so we explicitly yield to the event loop every 50 iterations. However, this 
isn't optimal as the 50 is obviously a magic number, determined by
experimentation on a couple of machines - when running on low spec hardware, 
this loop is almost certainly still janky. If we try and err on the side
of caution (eg, yielding every iteration) we see the wall time of the loop take 
a massive hit (around twice as long in that bug).

I'm wondering if there are any ideas about how to solve this optimally? Naively, it seems 
that the (broadest sense of the term) "platform" might be
able to help here using it's knowledge of the event-loop state - eg, a function that 
indicates "are we about to starve the event loop and become
janky?", or possibly even the whole hog (ie, "please yield to the event loop if 
you think now is a good time, otherwise just hand back a pre-resolved
promise").

Or maybe there are simpler options I've overlooked?

Thanks,

Mark

_______________________________________________
dev-platform mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to