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: refactor timer list processing #18582

Closed
wants to merge 2 commits into from

Conversation

apapirovski
Copy link
Member

@apapirovski apapirovski commented Feb 5, 2018

(The first commit is from #18579. I will rebase once that PR lands. Rebased.)

Currently timer handles have their processing function stored at kOnTimeout (which is an index = 0). This isn't actually completely efficient, even if the function is declared on the prototype, as it requires replacing when unref is called and un-assigning it when clearing timeouts. It also requires a property lookup in C++ which is a tad slow.

Instead, it's possible to pass in a function from JS to C++ at startup, similar to how Immediates work currently, which is then called from C++ and that function then decides what to do further (that is, whether to call listOnTimeout or unrefdHandle).

Locally, this change yields a roughly 10% improvement on the newly introduced benchmark for unpooled execution.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

benchmark, timers

@apapirovski apapirovski added c++ Issues and PRs that require attention from people who are familiar with C++. timers Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout. benchmark Issues and PRs related to the benchmark subsystem. lib / src Issues and PRs related to general changes in the lib or src directory. labels Feb 5, 2018
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. timers Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout. labels Feb 5, 2018
@apapirovski
Copy link
Member Author

@apapirovski
Copy link
Member Author

Benchmark results:

 timers/timers-breadth.js thousands=5000                     -1.37 %       ±2.96%   ±3.91%   ±5.02%
 timers/timers-cancel-pooled.js millions=5           ***   1587.57 %      ±88.31% ±116.88% ±150.93%
 timers/timers-cancel-unpooled.js millions=1         ***    106.69 %       ±7.78%  ±10.27%  ±13.20%
 timers/timers-depth.js thousands=1                   **      0.11 %       ±0.07%   ±0.09%   ±0.11%
 timers/timers-insert-pooled.js millions=5                    1.17 %       ±2.19%   ±2.89%   ±3.71%
 timers/timers-insert-unpooled.js millions=1                 -2.54 %       ±2.87%   ±3.79%   ±4.87%
 timers/timers-timeout-pooled.js millions=10                  2.63 %       ±5.60%   ±7.38%   ±9.48%
 timers/timers-timeout-unpooled.js millions=1        ***     20.32 %       ±4.07%   ±5.37%   ±6.91%

Nice bump on the timers-timeout-unpooled benchmark. The cancel bumps are from the first commit, which is from another PR.

@BridgeAR BridgeAR added the blocked PRs that are blocked by other issues or PRs. label Feb 6, 2018
Instead of using kOnTimeout index to track a special list
processing function, just pass in a function to C++ at
startup that executes all handles and determines which
function to call. This speeds up unpooled timeouts, as
well as cleaning up timers.
@apapirovski apapirovski removed the blocked PRs that are blocked by other issues or PRs. label Feb 8, 2018
@apapirovski
Copy link
Member Author

Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

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

LGTM

// then measures their execution on the next uv tick

const bench = common.createBenchmark(main, {
millions: [1],
Copy link
Member

@BridgeAR BridgeAR Feb 8, 2018

Choose a reason for hiding this comment

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

I personally do not like the "millions" and would actually like to replace those with e.g. n over time but that might only be my view on it. It is at least for me easier to read how many operations got executed that way instead of having to see that the output is actually also in millions.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the feedback. Changed over to n = 1e6.

setTimeout(i % 2 ? cb : cb2, 1).unref().ref();
}

bench.start();
Copy link
Member

Choose a reason for hiding this comment

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

I personally feel like it would also be better to move the start above the loop to include that time in the benchmark as I would say the creation time is important as well. But I guess you explicitly wanted to only measure the execution time?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, we have other tests that check the creation time. This way there's less noise in assessing the execution time.

@apapirovski
Copy link
Member Author

Hi @nodejs/collaborators — could you please review this timers PR? It's been a little while and I would like to get some reviews so it can be improved or land. Thanks.

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

@apapirovski apapirovski added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Feb 9, 2018
@apapirovski
Copy link
Member Author

Thanks everyone. Landed in 0f9efef

@apapirovski apapirovski closed this Feb 9, 2018
@apapirovski apapirovski deleted the patch-timers-process branch February 9, 2018 20:00
apapirovski added a commit that referenced this pull request Feb 9, 2018
Instead of using kOnTimeout index to track a special list
processing function, just pass in a function to C++ at
startup that executes all handles and determines which
function to call.

This change improves the performance of unpooled timeouts
by roughly 20%, as well as makes the unref/ref processing
easier to follow.

PR-URL: #18582
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
@MylesBorins
Copy link
Contributor

Should this be backported to v9.x-staging? If yes please follow the guide and raise a backport PR, if not let me know or add the dont-land-on label.

MayaLekova pushed a commit to MayaLekova/node that referenced this pull request May 8, 2018
Instead of using kOnTimeout index to track a special list
processing function, just pass in a function to C++ at
startup that executes all handles and determines which
function to call.

This change improves the performance of unpooled timeouts
by roughly 20%, as well as makes the unref/ref processing
easier to follow.

PR-URL: nodejs#18582
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
@MylesBorins
Copy link
Contributor

Opting to not land on v8.x, please lmk if we should reconsider

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. benchmark Issues and PRs related to the benchmark subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. 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