Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use microtask queue to flush autoruns... #306

Merged
merged 1 commit into from
Feb 2, 2018

Conversation

rwjblue
Copy link
Collaborator

@rwjblue rwjblue commented Jan 17, 2018

  • Replace the private _platform option, with a new _buildPlatform
  • Add interfaces for the constructor args for the Backburner class.
  • Move the main implementation of Backburner.prototype.end into a
    private method (_end) that is aware of if the end is from an autorun
    or manual run...
  • Extract steps to schedule an autorun out into stand alone private
    method (_scheduleAutorun)
  • Leverage microtask queue (via either promise.then(...) or
    MutationObserver) to schedule an autorun
  • Leverage microtask queue to advance from one queue to the next

This PR is just a small stepping stone towards leveraging microtasks a bit more (with the goal of removing Ember's autorun assertion)...

@rwjblue rwjblue requested a review from krisselden January 17, 2018 05:01
@rwjblue rwjblue force-pushed the autorun-microtask branch 3 times, most recently from 63ecfbf to 9e04bb8 Compare January 18, 2018 17:11
@rwjblue rwjblue changed the title Use Promise's to run scheduled autorun's in microtask queue. Use microtask queue to flush autoruns... Jan 18, 2018
@rwjblue
Copy link
Collaborator Author

rwjblue commented Jan 18, 2018

With the last commit (using MutationObserver when possible), the new test (confirming autorun flush happens before a bb.later(fn, 0)) passes on all supported browsers.

@stefanpenner
Copy link
Collaborator

stefanpenner commented Jan 18, 2018

seems good, this may need to be major bump, so it can ride the canary train in ember. Some caveats may exist re: popup blockers and window.open being run in autoruns.

Table of funky behavior is here: #181 (we may deem it irrelevant)

@stefanpenner stefanpenner mentioned this pull request Jan 18, 2018
5 tasks
@rwjblue
Copy link
Collaborator Author

rwjblue commented Jan 18, 2018

seems good, this may need to be major bump, so it can ride the canary train in ember

Ya, we definitely want it to go through a full canary -> beta -> release cycle so we can ensure this has no negative ramifications.

FWIW, I have been working on the next step (advancing from queue to queue during an autorun via microtask queue flushes) in rwjblue#1 if you are interested in the followup progress...

@stefanpenner
Copy link
Collaborator

FWIW, I have been working on the next step (advancing from queue to queue during an autorun via microtask queue flushes) in rwjblue#1 if you are interested in the followup progress...

Sounds like a good approach.

My long-term thought was to essentially make auto-run default, and if Ember.run is wrapping, abide by it. We can do a VC call if you want someone to chat about it.

@rwjblue
Copy link
Collaborator Author

rwjblue commented Jan 19, 2018

Yep, that’s exactly the direction I am pushing on. Will pester you tomorrow to chat through it some more 😆...

lib/index.ts Outdated
platform.clearNext = _platform.clearNext || platform.clearTimeout;
platform.now = _platform.now || (() => Date.now());

this._platform = platform;
// TODO: do we need this?
if (_platform.next) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we make this configurable, and just plug in RSVP's asap in ember? Then we avoid duplicate code

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make asap also use native Promise for its asap.

Copy link
Collaborator Author

@rwjblue rwjblue Jan 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefanpenner - I think we want to avoid the extra level of queuing that RSVP.asap does. Specifically we need to leverage the fact that microtasks that we enqueue are in the correct position (e.g. interleaving of native promises and RSVP.Promises should maintain the same resolve ordering).

@rwjblue rwjblue force-pushed the autorun-microtask branch 3 times, most recently from e3286b5 to 33755a5 Compare January 19, 2018 20:52
@@ -0,0 +1,53 @@
export interface IPlatform {
setTimeout(fn: () => void, ms: number): any;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn: Function

const SET_TIMEOUT = setTimeout;
const NOOP = () => {};

export function buildDefaultPlatform(flush: () => void): IPlatform {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we just configure asap?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m concerned with swapping to asap as it adds another layer of queuing and the exact ordering of interleaved RSVP promises, native promises, and BB queue transitions are super important...

However, this “host” interface style was explicitly designed to allow Ember to use RSVP.asap if it wants (it only needs to pass a _buildPlatform function that uses RSVP.asap for the provided next (you can see some examples in the tests)...

lib/index.ts Outdated
@@ -137,7 +151,7 @@ export default class Backburner {
return current;
}

public end() {
public end(fromAutorun = false) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to not expose this flag via a public API, we should maybe create _end that can have w/e flag, but if at all possible keep the existing one pristine (if possible).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, totally makes sense.

* Replace the private `_platform` option, with a new `_buildPlatform`
* Add interfaces for the constructor args for the `Backburner` class.
* Move the main implementation of `Backburner.prototype.end` into a
  private method (`_end`) that is aware of if the end is from an autorun
  or manual run...
* Extract steps to schedule an autorun out into stand alone private
  method (`_scheduleAutorun`)
* Leverage microtask queue (via either `promise.then(...)` or
  `MutationObserver`) to schedule an autorun
* Leverage microtask queue to advance from one queue to the next
@rwjblue
Copy link
Collaborator Author

rwjblue commented Feb 1, 2018

I just ran a series of benchmarks comparing various versions of backburner (v0.3.1 used by Ember 2.13, v1.3.4 used by Ember 2.18, v2.1.0 used by Ember 3.0.0-beta.5, master at e65437d, and this PR's changes) against a complex real world app.

As you can see below, compared to e65437d we have a very high confidence that this has a positive impact on performance (estimated difference is -153ms):

microtask-progression-vs-2-1-0

Full results

@rwjblue
Copy link
Collaborator Author

rwjblue commented Feb 1, 2018

@stefanpenner / @krisselden - I'd like to land this (given the strong evidence shown above) so that we can update Ember and continue fleshing out our plans RE: native promises and whatnot. Any objections?

@rwjblue rwjblue requested a review from stefanpenner February 1, 2018 05:09
@rwjblue rwjblue dismissed stefanpenner’s stale review February 1, 2018 08:05

Addressed and replied inline...

@rwjblue rwjblue merged commit 855b208 into BackburnerJS:master Feb 2, 2018
@rwjblue rwjblue deleted the autorun-microtask branch February 2, 2018 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants