Skip to content

benchmark: add test runner hooks and options#63754

Open
luanmuniz wants to merge 4 commits into
nodejs:mainfrom
luanmuniz:benchmark-test-runner-hooks-options
Open

benchmark: add test runner hooks and options#63754
luanmuniz wants to merge 4 commits into
nodejs:mainfrom
luanmuniz:benchmark-test-runner-hooks-options

Conversation

@luanmuniz

@luanmuniz luanmuniz commented Jun 5, 2026

Copy link
Copy Markdown

Add benchmarks for node:test hooks and test options. The hooks benchmark covers before, after, beforeEach, and afterEach, with a none mode as the baseline. The test options benchmark covers skip and todo behavior. This adds coverage for part of the benchmark/test_runner gaps tracked in the issue.

Refs: #55723

I eventually want to continue working on the Ref issue, and do the other benchmarks, but I decided to start with the simple ones that I can use existing files as a reference, get a feel for how the project works. Starting small and all of that. This will be my first (hopefully of many) contribution.

Please let me know if any changes or actions are required from me. I will wait for feedback before start tackling the other parts of the ref issue

Edit: I had some time today, and I started working on the other benchmarks, and I do have only, mock.timers and mock.module benchmarks ready too. I will await for feedback on the current code before pushing the other benchmarks. Please let me know if you prefer for me to push a different PR those since they have a bit more nuance, especially the mock.module one (Still nothing major tho)

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/performance

@nodejs-github-bot nodejs-github-bot added benchmark Issues and PRs related to the benchmark subsystem. test_runner Issues and PRs related to the test runner subsystem. labels Jun 5, 2026
Comment thread benchmark/test_runner/hooks.js Outdated
Comment on lines +30 to +46
describe(`${i}`, () => {
switch (hook) {
case 'before':
before(noop);
break;
case 'after':
after(noop);
break;
case 'beforeEach':
beforeEach(noop);
break;
case 'afterEach':
afterEach(noop);
break;
case 'none':
break;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also benchmarking the switch statement, which we don't want.

@luanmuniz

Copy link
Copy Markdown
Author

@avivkeller Changes done!

Obs: suite-tests.js, global-sequential-tests.js and global-concurrent-tests.js Seem to have the same switch problem. Should I fix that and include it in this PR?

Comment on lines +47 to +48
// eslint-disable-next-line prefer-const
let avoidV8Optimization = 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why 0 and why let?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It is let because we rewrite the values through the benchmark, and there is no particular reason to be 0, just didn't want to leave it undefined, and the original value of the variable shouldn't have an impact on this.

To be 100% honest, I don't quite understand the mechanics for this. I never dug into v8 optimizations before. The variable is there because I decided to follow the existing patterns inside this particular folder.

But please check this reference link and this for the comment that originally introduced this specific variable (Seems like the link is not working 100%, opening the discussion so just crtl+f for benchmark/test_runner/global-concurrent-tests.js and there should be a resolved review from H4ad with the reference)

Obs: I just realized the hooks are noops, and given that this variable works as described, I shouldn't have a noop there, so I'm pushing code so the hooks also have minimal execution within the function. Thanks for calling my attention to this.

@luanmuniz luanmuniz requested review from RafaelGSS and avivkeller June 9, 2026 11:06
@luanmuniz

Copy link
Copy Markdown
Author

@RafaelGSS @avivkeller Both feedbacks are addressed. Please let me know if it's resolved or if any changes are still needed.

@luanmuniz

luanmuniz commented Jun 17, 2026

Copy link
Copy Markdown
Author

Ping @RafaelGSS @avivkeller

I'm waiting for this PR to be done so I can continue working on the other benchmarks and hopefully close the Ref issue.
Please let me know of any requirements here. Thank you!

I have additional local benchmarks for mock.timers, mock.module, and only, but I’ll keep this PR scoped to hooks/options unless maintainers prefer that I expand it. Happy to split follow-ups however is easiest to review.

Comment thread benchmark/test_runner/hooks.js Outdated
} = require('node:test');

const bench = common.createBenchmark(main, {
n: [1, 10, 100, 1000],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are these numbers arbitrarily chosen? Please use https://github.com/nodejs/node/blob/main/benchmark/calibrate-n.js

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes and No. I took those numbers from another benchmark in the same folder since I didn't know exactly how the configurations were used forward.

That being said, I didn't know about calibrate-n and how it worked, but after some study, I think I understand it now. I'm running it for both this and the PR for mock-timers. I will post the results here as soon as I have them and update the numbers with the best one found.

@RafaelGSS RafaelGSS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm uncertain that the number of configs for the benchmarks is useful. Our benchmark suite is already too big, any configuration you add increases the suite run exponentially.

It would be great to share the current results too.

Comment thread benchmark/test_runner/test-options.js Outdated
const { it } = require('node:test');

const bench = common.createBenchmark(main, {
n: [1, 10, 100, 1000],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please use calibrate N here.

Add benchmarks for node:test hooks and test options.
The hooks benchmark covers before, after, beforeEach, and afterEach, with a none mode as the baseline.
The test options benchmark covers skip and todo behavior. This adds coverage for part of the benchmark/test_runner gaps tracked in the issue.

Refs: nodejs#55723
Signed-off-by: Luan Muniz <luan@luanmuniz.com.br>
Select each benchmark variant before starting the timer so the
measured loop does not include dispatch overhead.

Signed-off-by: Luan Muniz <luan@luanmuniz.com.br>
Update the hooks benchmark so registered hooks perform the same
anti-optimization assignment as test bodies instead of calling a noop.
This keeps the measured hook path from using an empty callback.

Links for more information on this actions:
nodejs#48931 (comment)
https://www.mail-archive.com/v8-users@googlegroups.com/msg05521.html

Signed-off-by: Luan Muniz <luan@luanmuniz.com.br>
Use calibrated n values for the test runner hooks and options benchmarks.
Reduce the test options benchmark configurations to keep the benchmark suite smaller.

Signed-off-by: Luan Muniz <luan@luanmuniz.com.br>
@luanmuniz luanmuniz force-pushed the benchmark-test-runner-hooks-options branch from d8f7882 to d4ab1a9 Compare June 25, 2026 10:54
@luanmuniz

Copy link
Copy Markdown
Author

Hi there, sorry for the force-push. I had a local git history issue while cleaning up the branch, and I force-pushed to get the PR back into the intended state. Apologies for the noise. I’ll be more careful with the branch history going forward.

I've used calibrate-n, and there are the results in case you want to take a look:
calibrate-hooks.txt
calibrate-test-options.txt

The script asked for 10K for both benchmarks, but in my opinion, the hooks.js was taking too long to run with 10K, so I went with the second-best choice there.

Also, I found a small bug in the calibrate-n code: it wasn't using the correct arguments and was always using the const defaults instead. Is it best to open another PR for just that, or add that change here?

CC @RafaelGSS

@luanmuniz luanmuniz requested a review from RafaelGSS June 25, 2026 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

benchmark Issues and PRs related to the benchmark subsystem. test_runner Issues and PRs related to the test runner subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants