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

run microtasks before ticks #51267

Closed
wants to merge 1 commit into from
Closed

Conversation

ronag
Copy link
Member

@ronag ronag commented Dec 23, 2023

This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work.

Enable experimental task ordering. Always drain micro task queue before running process.nextTick to avoid unintuitive behavior and unexpected logical deadlocks when mixing async callback and event API's with Promise, async/await and queueMicroTask.

Refs: #51156
Refs: #51156
Refs: #51114 (comment)
Refs: #51070
Refs: #51156

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. process Issues and PRs related to the process subsystem. labels Dec 23, 2023
ronag added a commit to nxtedition/node that referenced this pull request Dec 23, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114 (comment)
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
ronag added a commit to nxtedition/node that referenced this pull request Dec 23, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
@ronag ronag added the semver-major PRs that contain breaking changes and should be released in the next major version. label Dec 23, 2023
@meyfa

This comment was marked as resolved.

@jasnell
Copy link
Member

jasnell commented Dec 23, 2023

If think that IF we do this, which is something we need to very carefully consider given the very real chance of breakage, we should include an escape hatch in the form of a command-line argument that restores the original ordering. We can eventually deprecate that flag once the ecosystem has had a while to make the transition.

./node --legacy-microtask-ordering

ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
@ronag ronag requested a review from mcollina December 24, 2023 10:35
@ronag
Copy link
Member Author

ronag commented Dec 24, 2023

What about having it as an opt-in for now?

ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
@ronag
Copy link
Member Author

ronag commented Dec 24, 2023

It might be difficult or impossible to have this by default but I still think we need to have the possibility to opt-in as this is the only way to get "correct" behavior.

ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

I would prefer if this super-hot function would not get a few more ifs. I think you could duplicate the implementation and only change the export.

This pattern would also allow us for more experimentation.

ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
ronag added a commit to nxtedition/node that referenced this pull request Dec 24, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@ronag
Copy link
Member Author

ronag commented Dec 24, 2023

Please note that this is necessary as queueMicrotask is not sufficient to replace the current nextTick due to its re-entrance behavior.

@ronag
Copy link
Member Author

ronag commented Dec 25, 2023

@mcollina I can't get this to work without a function wrapper due to the following lint rule:

node:internal/options:20
    ({ options: optionsMap } = getCLIOptions());
                               ^

Error: Should not query options before bootstrapping is done
    at getCLIOptionsFromBinding (node:internal/options:20:32)
    at getOptionValue (node:internal/options:45:19)
    at setupTaskQueue (node:internal/process/task_queues:210:34)
    at node:internal/bootstrap/node:306:38

Any suggestions? Or who might have some idea?

@ronag
Copy link
Member Author

ronag commented Dec 25, 2023

@joyeecheung You are the one that added the rule I believe?

lib/internal/process/task_queues.js Outdated Show resolved Hide resolved
lib/internal/process/task_queues.js Outdated Show resolved Hide resolved
@ronag ronag added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 27, 2023
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Dec 27, 2023
@nodejs-github-bot
Copy link
Collaborator

callback();
} else {
const args = tock.args;
switch (args.length) {
Copy link
Member

Choose a reason for hiding this comment

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

is this actually faster?

@ronag ronag force-pushed the ticks-and-rejections branch 4 times, most recently from a88c594 to 3a1c141 Compare December 29, 2023 19:36
ronag added a commit to nxtedition/node that referenced this pull request Dec 29, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
@ronag ronag added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 29, 2023
This resolve multiple timing issues related to promises
and nextTick. As well as resolving zaldo in promise only
code, i.e. our current best practice of using process.nextTick
will always apply and work.

Refs: nodejs#51156
Refs: nodejs#51156 (comment)
Refs: nodejs#51114
Refs: nodejs#51070
Refs: nodejs#51156

PR-URL: nodejs#51267
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Dec 29, 2023
@nodejs-github-bot
Copy link
Collaborator


> Stability: 1 - Experimental
Enable experimental task ordering. Always drain micro task queue
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Enable experimental task ordering. Always drain micro task queue
Enable experimental task ordering. Always drain Microtasks queue

It would also be useful to link to a doc like https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide#microtasks here.

Enable experimental task ordering. Always drain micro task queue
before running `process.nextTick` to avoid unintuitive behavior
and unexpected logical deadlocks when mixing async callback and
event API's with `Promise`, `async`/`await`` and `queueMicroTask`.
Copy link
Member

Choose a reason for hiding this comment

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

Can you provide some examples? Without examples I doubt how many users would be able to recognize whether this can be useful for them and pick up this option.

Also note that we have a section in process.md saying..

every time the "next tick queue" is drained, the microtask queue
is drained immediately after.

I think that should be updated to mention this option.

@ronag ronag closed this Jan 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-ci PRs that need a full CI run. process Issues and PRs related to the process subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants