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

timers: improve setImmediate() performance #4169

Merged
merged 1 commit into from
Mar 18, 2016

Conversation

mscdex
Copy link
Contributor

@mscdex mscdex commented Dec 6, 2015

This commit improves setImmediate() performance by moving the try-finally block that wraps callback execution into a separate function because currently v8 never tries to optimize functions that contain try-finally blocks.

With this change, there is a ~20-40% improvement in the included setImmediate() depth benchmarks. The breadth benchmarks show a slight improvement.

@mscdex mscdex added the timers Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout. label Dec 6, 2015
@JungMinu
Copy link
Member

JungMinu commented Dec 6, 2015

@JungMinu
Copy link
Member

JungMinu commented Dec 6, 2015

CI is happy except for unrelated Windows test :)

@JungMinu
Copy link
Member

JungMinu commented Dec 6, 2015

LGTM @Fishrock123 LGTY? :)

@@ -409,6 +393,26 @@ function processImmediate() {
}
}

function tryOnImmediate(immediate, queue) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hah, beat me to it I see. :P

I was going to leave this until after #4007, in part so that it would look similar.

I suggest we keep the naming consistent in some way with https://github.com/nodejs/node/pull/4007/files#diff-0a5d4868b2b9b17cf9e2c11f1bd1311eR177

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've been using the try prefix with the try-catch/finally isolation PRs I've submitted in the past as that seems (to me) to make it more clear as to what the isolation functions are doing. shrug

Copy link
Contributor

Choose a reason for hiding this comment

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

I changed the one in #4007 to _tryOnTimeout, keeping the underspace from a prior incantation in internal timeouts. Mind adding it to this then?

@jasnell
Copy link
Member

jasnell commented Dec 11, 2015

LGTM so long as @Fishrock123 is happy

@@ -0,0 +1,21 @@

Copy link
Member

Choose a reason for hiding this comment

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

Forgot a 'use strict'?

@bnoordhuis
Copy link
Member

I'd rewrite the benchmarks so that the callbacks don't reference free variables (including bench.end().) Right now, they appear to be creating 5 or 10 million closures, making it as much a GC benchmark as a timers benchmark.

@jasnell
Copy link
Member

jasnell commented Jan 15, 2016

@mscdex @Fishrock123 ... ping :-)

'use strict';

var common = require('../common.js');
var bench = common.createBenchmark(main, {
Copy link
Member

Choose a reason for hiding this comment

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

const ?

@mscdex
Copy link
Contributor Author

mscdex commented Jan 15, 2016

@bnoordhuis I tried to rewrite the benchmarks according to your suggestions, but at least judging by the results of --trace-gc, I didn't see any difference. Let me know if it now looks better to you.

@jasnell Updated per your suggestions too.

@Fishrock123
Copy link
Contributor

I'll try to look tomorrow

@mscdex
Copy link
Contributor Author

mscdex commented Feb 7, 2016

@bnoordhuis @Fishrock123 ping

@jasnell
Copy link
Member

jasnell commented Feb 7, 2016

@mscdex .. LGTM

@bnoordhuis
Copy link
Member

LGTM

@Fishrock123
Copy link
Contributor

Will take a look when I get back home

@jasnell
Copy link
Member

jasnell commented Feb 10, 2016

Marking this lts-watch but it would definitely need to sit for a while in master and v5 before pulling back

@ChALkeR ChALkeR added the performance Issues and PRs related to the performance of Node.js. label Feb 16, 2016
@mscdex
Copy link
Contributor Author

mscdex commented Feb 21, 2016

@Fishrock123 Does this LGTY?

immediate._onImmediate();
threw = false;
} finally {
if (threw === true) {
Copy link
Contributor

Choose a reason for hiding this comment

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

early return to avoid more indentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you return early in a finally block, the exception wouldn't be thrown, which would change behavior.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I follow, how would that change?

The try - finally will still catch the exception?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you do something like

function foo() {
  try {
    throw new Error('foo');
  } finally {
    return;
  }
}

the exception won't be thrown and execution will continue normally (as if you had done try { } catch (e) {}, but without access to the exception object). If you remove the return from the finally block, execution will continue to the end of the finally block at which point the exception will be thrown.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm I was under the impression we swallowed it for some reason, I guess this allows it to bubble up to the console?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would assume so. Only try {} catch(e) {} or try {} finally { ... return; ... } can swallow exceptions.

@Fishrock123
Copy link
Contributor

New CI with rebase onto master: https://ci.nodejs.org/job/node-test-pull-request/1713/

@Fishrock123
Copy link
Contributor

it would definitely need to sit for a while in master and v5 before pulling back

I disagree. The implementation is effectively identical. This should land like any other patch fix.

@@ -418,6 +404,27 @@ function processImmediate() {
}


function tryOnImmediate(immediate, queue) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you move the deopt comment to here and clarify it a tad, ala https://github.com/nodejs/node/pull/4007/files#diff-0a5d4868b2b9b17cf9e2c11f1bd1311eR178 ? (I do need to add the v8 version to mine also..)

Fishrock123 added a commit to Fishrock123/node that referenced this pull request Feb 25, 2016
rename to match Brian’s setImmediate() refactor in
nodejs#4169
@mscdex mscdex force-pushed the perf-setimmediate branch 2 times, most recently from bd485e9 to 75e02de Compare March 18, 2016 03:17
@mscdex
Copy link
Contributor Author

mscdex commented Mar 18, 2016

Made suggested changes. CI: https://ci.nodejs.org/job/node-test-pull-request/1953/

@mscdex
Copy link
Contributor Author

mscdex commented Mar 18, 2016

@Fishrock123 LGTY?

@Fishrock123
Copy link
Contributor

@mscdex lgtm

This commit improves setImmediate() performance by moving the
try-finally block that wraps callback execution into a separate
function because currently v8 never tries to optimize functions
that contain try-finally blocks.

With this change, there is a ~20-40% improvement in the included
setImmediate() depth benchmarks. The breadth benchmarks show a slight
improvement.

PR-URL: nodejs#4169
Reviewed-By: Minwoo Jung <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Jeremiah Senkpiel <[email protected]>
@mscdex mscdex merged commit 089bef0 into nodejs:master Mar 18, 2016
@mscdex mscdex deleted the perf-setimmediate branch March 18, 2016 23:30
Fishrock123 pushed a commit that referenced this pull request Mar 22, 2016
This commit improves setImmediate() performance by moving the
try-finally block that wraps callback execution into a separate
function because currently v8 never tries to optimize functions
that contain try-finally blocks.

With this change, there is a ~20-40% improvement in the included
setImmediate() depth benchmarks. The breadth benchmarks show a slight
improvement.

PR-URL: #4169
Reviewed-By: Minwoo Jung <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Jeremiah Senkpiel <[email protected]>
Fishrock123 added a commit that referenced this pull request Mar 23, 2016
Notable changes:

* buffer: Now properly throws RangeErrors on out-of-bounds writes (Matt
Loring) #5605
  - This effects write{Float|Double} when the noAssert option is not
used.
* timers:
  - Returned timeout objects now have a Timeout constructor name
(Jeremiah Senkpiel) #5793
  - Performance of Immediate processing is now ~20-40% faster (Brian
White) #4169
* vm: Fixed a contextify regression introduced in v5.9.0 (Ali Ijaz
Sheikh) #5800

PR-URL: #5831
Fishrock123 added a commit that referenced this pull request Mar 23, 2016
Notable changes:

* buffer: Now properly throws RangeErrors on out-of-bounds writes (Matt
Loring) #5605
  - This effects write{Float|Double} when the noAssert option is not
used.
* timers:
  - Returned timeout objects now have a Timeout constructor name
(Jeremiah Senkpiel) #5793
  - Performance of Immediate processing is now ~20-40% faster (Brian
White) #4169
* vm: Fixed a contextify regression introduced in v5.9.0 (Ali Ijaz
Sheikh) #5800

PR-URL: #5831
Fishrock123 added a commit that referenced this pull request Mar 23, 2016
Notable changes:

* buffer: Now properly throws RangeErrors on out-of-bounds writes (Matt
Loring) #5605
  - This effects write{Float|Double} when the noAssert option is not
used.
* timers:
  - Returned timeout objects now have a Timeout constructor name
(Jeremiah Senkpiel) #5793
  - Performance of Immediate processing is now ~20-40% faster (Brian
White) #4169
* vm: Fixed a contextify regression introduced in v5.9.0 (Ali Ijaz
Sheikh) #5800

PR-URL: #5831
Fishrock123 added a commit to Fishrock123/node that referenced this pull request Mar 24, 2016
Notable changes:

* buffer: Now properly throws RangeErrors on out-of-bounds writes (Matt
Loring) nodejs#5605
  - This effects write{Float|Double} when the noAssert option is not
used.
* timers:
  - Returned timeout objects now have a Timeout constructor name
(Jeremiah Senkpiel) nodejs#5793
  - Performance of Immediate processing is now ~20-40% faster (Brian
White) nodejs#4169
* vm: Fixed a contextify regression introduced in v5.9.0 (Ali Ijaz
Sheikh) nodejs#5800

PR-URL: nodejs#5831
@mscdex mscdex mentioned this pull request Apr 28, 2016
3 tasks
@MylesBorins
Copy link
Contributor

Setting as don't land for the same reason as #4007 (comment)

Keeping the timers changes in v6. Open to discussion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Issues and PRs related to the performance of Node.js. timers Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants