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

Performance issue with Promise rejection chaining #25000

Closed
hexpunk opened this issue Dec 12, 2018 · 3 comments
Closed

Performance issue with Promise rejection chaining #25000

hexpunk opened this issue Dec 12, 2018 · 3 comments

Comments

@hexpunk
Copy link

hexpunk commented Dec 12, 2018

  • Version: v6.15.1, v8.14.0, v10.14.2, v11.4.0

  • Platform: Darwin Kernel Version 18.2.0: Fri Oct 5 19:41:49 PDT 2018; root:xnu-4903.221.2~2/RELEASE_X86_64 x86_64, Linux 4.15.0-29-generic Updates README with IRC channel for #io.js #31~16.04.1-Ubuntu SMP Wed Jul 18 08:54:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

  • Subsystem: Promise

I've found all versions of Node that I've tried hang after a long number of chained rejected Promises.

This script creates a large number of chained promises where each promise is added to the chain upon the previous promise being resolved.

const requests = [...Array(100000).keys()];

const acceptance = arg => new Promise(resolve => resolve(arg));

function handleSuccessAndContinue() {
  if (requests.length > 0) {
    return acceptance(requests.pop())
      .then(handleSuccessAndContinue);
  } else {
    console.log('finish: ' + new Date().toISOString());
  }
}

console.log('start:  ' + new Date().toISOString());

acceptance(requests.pop())
  .then(handleSuccessAndContinue);

If I run this script using this command (node promise.resolve.js && printf "exit: " && TZ=Zulu gdate -Ins) to track roughly the time it takes to run, I get these results:

start:  2018-12-12T21:12:04.923Z
finish: 2018-12-12T21:12:04.979Z
exit:   2018-12-12T21:12:05,008461000+00:00

Here we can see that it takes less than a second to run the actual code and the Node process quits very soon afterwards.

However, take this following script, which does basically the same thing as the last, but chains on Promise rejections rather than resolution.

const requests = [...Array(100000).keys()];

const rejection = arg => new Promise((_, reject) => reject(arg));

function handleFailureAndContinue() {
  if (requests.length > 0) {
    return rejection(requests.pop())
      .catch(handleFailureAndContinue);
  } else {
    console.log('finish: ' + new Date().toISOString());
  }
}

console.log('start:  ' + new Date().toISOString());

rejection(requests.pop())
  .catch(handleFailureAndContinue);

After running the same command to roughly time its execution (node promise.reject.js && printf "exit: " && TZ=Zulu gdate -Ins), here are the results:

start:  2018-12-12T21:15:47.586Z
finish: 2018-12-12T21:15:47.691Z
exit:   2018-12-12T21:16:35,380746000+00:00

Once again, the actual code completes in less than a second. However, the Node process continues to run for 48 seconds while hitting 100% CPU utilization for that period before finally exiting. The amount of time between finishing execution of the script and exiting the process grows in relation with the number of promises that are processed. (I started from 10 and increased the size of the requests array by magnitude until I reached the first number that caused a noticeable pause on my computer.)

This appears to be an issue with Node's implementation of Promise because this behavior is not exhibited when I add var Promise = require("bluebird"); at the top of the script.

@TimothyGu
Copy link
Member

Profiling shows that this is because emitPromiseRejectionWarnings() is triggered for a large number of rejected promises:

image

@hexpunk
Copy link
Author

hexpunk commented Dec 12, 2018

What can be done about this? Also, could this possibly be related to #18207?

@jasnell
Copy link
Member

jasnell commented Jun 26, 2020

This does not appear to be actionable and there's been no activity. Closing

@jasnell jasnell closed this as completed Jun 26, 2020
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

No branches or pull requests

3 participants