process: js fast path for cached bindings#18365
process: js fast path for cached bindings#18365apapirovski wants to merge 4 commits intonodejs:masterfrom
Conversation
lib/internal/bootstrap_node.js
Outdated
|
|
||
| process.binding = function binding(module) { | ||
| if (!module || typeof module !== 'string') | ||
| return; |
There was a problem hiding this comment.
It’s unfortunate, but process.binding is used in the wild too often for us to be able to just return undefined if the requested module is undefined. We should cast it to a string just as the C++ version did.
There was a problem hiding this comment.
Also, when would core code call it with something that is not a string? This guard should probably just go.
bnoordhuis
left a comment
There was a problem hiding this comment.
If you're adding caching in JS land, then I'd get rid of env->binding_cache_object() +env->internal_binding_cache_object() and strip down node::Binding() and node::InternalBinding() to their bare essentials.
lib/internal/bootstrap_node.js
Outdated
|
|
||
| process.binding = function binding(module) { | ||
| if (!module || typeof module !== 'string') | ||
| return; |
There was a problem hiding this comment.
Also, when would core code call it with something that is not a string? This guard should probably just go.
|
@TimothyGu @bnoordhuis Thanks for the feedback. I've updated the PR based on your suggestions. |
bnoordhuis
left a comment
There was a problem hiding this comment.
LGTM modulo comment. Binding() and InternalBinding() have quite some shared logic you could factor out.
lib/internal/bootstrap_node.js
Outdated
| if (typeof bindingObj[module] === 'object') | ||
| return bindingObj[module]; | ||
| bindingObj[module] = getLinkedBinding(module); | ||
| return bindingObj[module]; |
There was a problem hiding this comment.
Minor anti-pattern, looking up twice. Do this instead:
let mod = bindingObj[module];
if (typeof mod !== 'object')
mod = bindingObj[module] = getBinding(module);
return mod;There was a problem hiding this comment.
Good catch, don't know what I was thinking :) Updated.
f45097e to
ea60d2c
Compare
|
Ok, I've added one final change in terms of moving |
joyeecheung
left a comment
There was a problem hiding this comment.
Nice, this also gives me a good idea where to monkey-patch the deprecate bindings....
|
Landed in bb27bfe |
Currently, both process.binding and internalBinding have to call into C++ regardless of whether the module has been cached or not. This creates significant overhead to all binding calls and unfortunately the rest of the codebase doesn't really optimize the amount of times that bindings are required (as an example: 12 files require the async_wrap binding). Changing all the usage of this function throughout the codebase would introduce a lot of churn (and is kind of a hassle) so instead this PR introduces a JS fast path for both functions for cases where the binding has already been cached. While micro benchmarks are not super meaningful here (it's not like we call binding that often...), this does speed up the cached call by 400%. In addition, move moduleLoadList creation and management entirely into JS-land as it requires less code and is more efficient. PR-URL: #18365 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Currently, both process.binding and internalBinding have to call into C++ regardless of whether the module has been cached or not. This creates significant overhead to all binding calls and unfortunately the rest of the codebase doesn't really optimize the amount of times that bindings are required (as an example: 12 files require the async_wrap binding). Changing all the usage of this function throughout the codebase would introduce a lot of churn (and is kind of a hassle) so instead this PR introduces a JS fast path for both functions for cases where the binding has already been cached. While micro benchmarks are not super meaningful here (it's not like we call binding that often...), this does speed up the cached call by 400%. In addition, move moduleLoadList creation and management entirely into JS-land as it requires less code and is more efficient. PR-URL: #18365 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
|
Does this make sense for LTS? |
|
@MylesBorins I think it makes sense to backport this to v8.x, I am trying to backport #19112 to v8.x but a test fails because it depends on this to get a complete fix. @apapirovski are you working on a backport? I can help backporting this one in order to get #19112 backported. |
Currently, both process.binding and internalBinding have to call into C++ regardless of whether the module has been cached or not. This creates significant overhead to all binding calls and unfortunately the rest of the codebase doesn't really optimize the amount of times that bindings are required (as an example: 12 files require the async_wrap binding). Changing all the usage of this function throughout the codebase would introduce a lot of churn (and is kind of a hassle) so instead this PR introduces a JS fast path for both functions for cases where the binding has already been cached. While micro benchmarks are not super meaningful here (it's not like we call binding that often...), this does speed up the cached call by 400%. In addition, move moduleLoadList creation and management entirely into JS-land as it requires less code and is more efficient. PR-URL: nodejs#18365 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
|
@joyeecheung if you could backport to 8.x that would be great. should we set |
Currently, both process.binding and internalBinding have to call into C++ regardless of whether the module has been cached or not. This creates significant overhead to all binding calls and unfortunately the rest of the codebase doesn't really optimize the amount of times that bindings are required (as an example: 12 files require the async_wrap binding). Changing all the usage of this function throughout the codebase would introduce a lot of churn (and is kind of a hassle) so instead this PR introduces a JS fast path for both functions for cases where the binding has already been cached. While micro benchmarks are not super meaningful here (it's not like we call binding that often...), this does speed up the cached call by 400%. In addition, move moduleLoadList creation and management entirely into JS-land as it requires less code and is more efficient. PR-URL: nodejs#18365 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
|
ping @joyeecheung regarding a 8.x backport |
Currently, both process.binding and internalBinding have to call into C++ regardless of whether the module has been cached or not. This creates significant overhead to all binding calls and unfortunately the rest of the codebase doesn't really optimize the amount of times that bindings are required (as an example: 12 files require the async_wrap binding). Changing all the usage of this function throughout the codebase would introduce a lot of churn (and is kind of a hassle) so instead this PR introduces a JS fast path for both functions for cases where the binding has already been cached. While micro benchmarks are not super meaningful here (it's not like we call binding that often...), this does speed up the cached call by 400%. In addition, move moduleLoadList creation and management entirely into JS-land as it requires less code and is more efficient. PR-URL: nodejs#18365 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Currently, both
process.bindingandinternalBindinghave to call into C++ regardless of whether the module has been cached or not. This creates significant overhead to all binding calls and unfortunately the rest of the codebase doesn't really optimize the amount of times that bindings are required (as an example: 12 files require the async_wrap binding).Changing all the usage of this function throughout the codebase would introduce a lot of churn (and is kind of a hassle) so instead this PR introduces a JS fast path for both functions for cases where the binding has already been cached. While micro benchmarks are not super meaningful here (it's not like we call
bindingthat often...), this does speed up the cached call by 400%.Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passesAffected core subsystem(s)
process, src