Skip to content

async_hooks: faster AsyncResource#bind() - #43065

Closed
bengl wants to merge 1 commit into
nodejs:mainfrom
bengl:bengl/faster-bind
Closed

async_hooks: faster AsyncResource#bind()#43065
bengl wants to merge 1 commit into
nodejs:mainfrom
bengl:bengl/faster-bind

Conversation

@bengl

@benglbengl commented May 12, 2022

Copy link
Copy Markdown
Member

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 ObjectDefinePropertystill 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-botnodejs-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
Copy Markdown
Collaborator

@juanarboljuanarbol 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.

Lgtm

@bengl
bengl marked this pull request as draft May 12, 2022 06:24
@bengl

bengl commented May 12, 2022

Copy link
Copy Markdown
MemberAuthor

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
benglforce-pushed the bengl/faster-bind branch from 212ea52 to 003b50bCompareMay 12, 2022 14:08
@bengl

Copy link
Copy Markdown
MemberAuthor

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.

@mcollinamcollina 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.

LGTM

How did you found this was a bottleneck? :D

@bengl

Copy link
Copy Markdown
MemberAuthor

@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
Copy Markdown
MemberAuthor

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Comment threadlib/async_hooks.js
value: this,
writable: true,
}
ObjectDefineProperty(bound, 'length', {

Copy link
Copy Markdown
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
Copy Markdown
Collaborator

@bengl

Copy link
Copy Markdown
MemberAuthor

Closing since #46432 precludes this.

@benglbengl closed this Nov 12, 2023
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

async_hooksIssues and PRs related to the async hooks subsystem.needs-ciPRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

14 participants

@bengl@nodejs-github-bot@mcollina@Qard@lpinca@rochdev@tniessen@JungMinu@legendecas@juanarbol@Flarna@RafaelGSS@puzpuzpuz@RaisinTen