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

async_hooks: faster AsyncResource#bind() #43065

Closed
wants to merge 1 commit into from

Conversation

bengl
Copy link
Member

@bengl bengl commented May 12, 2022

FunctionPrototypeBind preserves length, and the asyncResource property can just be set normally, avoiding the costly call to ObjectDefineProperties. In the thisArg === undefined case, reducing it to a single ObjectDefineProperty still has tangible performance gain.

I added a benchmark and here is the output on my machine (the ./node-master result is without this commit, and the ./node result is with it):

$ ./node benchmark/async_hooks/async-resource-bind.js
async_hooks/async-resource-bind.js option="withThisArg" n=1e+100: 5.619836901644185e+99
async_hooks/async-resource-bind.js option="withoutThisArg" n=1e+100: 5.96856136341294e+99
$ ./node-master benchmark/async_hooks/async-resource-bind.js
async_hooks/async-resource-bind.js option="withThisArg" n=1e+100: 1.5451341226758954e+99
async_hooks/async-resource-bind.js option="withoutThisArg" n=1e+100: 1.605511858099379e+99
(Expand here for old/incorrect benchmark.)
$ ./node benchmark/async_hooks/async-resource-bind.js
async_hooks/async-resource-bind.js option="withThisArg" n=1e+100: 4.6615746235960295e+100
async_hooks/async-resource-bind.js option="withoutThisArg" n=1e+100: 5.939287298590602e+100
$ ./node-master benchmark/async_hooks/async-resource-bind.js
async_hooks/async-resource-bind.js option="withThisArg" n=1e+100: 1.6248803889798304e+99
async_hooks/async-resource-bind.js option="withoutThisArg" n=1e+100: 1.6487041313302313e+99

cc @nodejs/async_hooks

@nodejs-github-bot nodejs-github-bot added async_hooks Issues and PRs related to the async hooks subsystem. needs-ci PRs that need a full CI run. labels May 12, 2022
@nodejs-github-bot
Copy link
Collaborator

Copy link
Member

@juanarbol juanarbol left a comment

Choose a reason for hiding this comment

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

Lgtm

@bengl bengl marked this pull request as draft May 12, 2022 06:24
@bengl
Copy link
Member Author

bengl commented May 12, 2022

Looks like I submitted too soon again here.

While FunctionPrototypeBind does preserve length, it's preserving the length of runInAsyncScope, and not the fn in question. It will need to preserve the length the same way as the other code path, but I since I suspect that it will still be significantly faster, I'm going to leave this open in Draft mode until I can clean it up (hopefully in the next day or two).

@bengl bengl force-pushed the bengl/faster-bind branch from 212ea52 to 003b50b Compare May 12, 2022 14:08
@bengl
Copy link
Member Author

bengl commented May 12, 2022

Setting this as "ready for review" again. It's now always doing an ObjectDefineProperty, but that's still about a 3.7x improvement on my machine.

@bengl bengl marked this pull request as ready for review May 12, 2022 14:15
@nodejs-github-bot

This comment was marked as outdated.

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

How did you found this was a bottleneck? :D

@bengl
Copy link
Member Author

bengl commented May 12, 2022

@mcollina .bind() is a pretty hot path with a lot of the new changes (and some upcoming ones) in our APM tracing library, so I was investigating it directly.

@bengl
Copy link
Member Author

bengl commented May 12, 2022

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

value: this,
writable: true,
}
ObjectDefineProperty(bound, 'length', {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just stop doing this completely? This is only one of the cases needed to preserve the original functionality as the function could also have other properties or symbols attached to it for example, and those wouldn't be copied. Maybe the best approach then would be to copy nothing and leave it to the user to decide what needs copying. Then the implementation will be as fast as it can be and will only become slower if the user decides that copying properties is needed.

@nodejs-github-bot
Copy link
Collaborator

@bengl
Copy link
Member Author

bengl commented Nov 12, 2023

Closing since #46432 precludes this.

@bengl bengl closed this Nov 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
async_hooks Issues and PRs related to the async hooks subsystem. needs-ci PRs that need a full CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.