-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
Improve performance of accessing globals in scripts running in vm
modules
#31658
Comments
There is nothing node can do to help performance here. The problem is that V8's global proxy design forces the embedder to indirect through c++ for every lookup, which adds a lot of overhead. |
And there's no way to cache/circumvent that lookup i node? If not, do you think there's any chance of v8 making changes so we can work around it? Or are there any workarounds similar to the current workaround we can for |
@SimenB You could do In the long term V8 might need to refactor this system anyway because of the upcoming realms API, so maybe one day |
@devsnek I mentioned that in the OP - it takes the time from 1600ms to 800ms (so halves the time), but it's still 2 orders of magnitude slower than injecting it (which is less than 10ms). I see no difference between |
@SimenB it seems that at some point we started creating the internal proxy unconditionally, which is why you're not seeing a speedup with what i suggested. |
Using the |
Ah, wonderful! |
I just compiled your branch and can confirm it does indeed fix the issue 😀 🤞 you're able to land it! Might be a bit premature, but do you think it'll be backported to v10 and v12? Since it's a different API graceful degradation should be fine, but the free performance boost for all release line would be wonderful (and Jest could remove the option we added to allow people to work around this) |
Fixes nodejs#855 Fixes nodejs#31658 Fixes nodejs#31808
Fixed on 4725ac6 :) |
Sorry, @SimenB is this issue solved? |
I don't think so, #30709 was closed unmerged? |
Please land it, it would make me very happy 😀 |
Also note that this issue is known as far back as 2016: nodejs/benchmarking#75 (comment). |
Is your feature request related to a problem? Please describe.
Accessing globals from within a
vm.Script
is guarded by interceptors which makes accessing them slow, (from my understanding, @fhinkel has an excellent comment explaining some of this here: jestjs/jest#5163 (comment)). The suggested workaround is to evaluate and cache the global you want access to (Math
in my example case below) and inject that into thevm.Script
. This is an acceptable workaround forvm.Script
andvm.compileFunction
but it cannot be done when using ESMvm.SourceTextModule
as there is no wrapping function call.I've put together this script you can run to see the numbers:
Running this gives the following results on my machine:
So ~1600ms if not using the workaround, which reduces it to ~7ms.
Describe the solution you'd like
I'd like for accessing globals to be as fast, or as close to as possible, as fast as accessing globals outside of
vm
. Would it be possible for Node'svm
implementation to cache the global property lookups, so that the price is only paid once instead of on every single access?Describe alternatives you've considered
As mentioned, caching and injecting the global manually works when there is a function wrapper, but this doesn't work with ESM. I've tried assigning the
Math
global to thecontext
, and while that halves the time spent (~800ms), it's still 2 orders of magnitude slower than injecting a reference.The text was updated successfully, but these errors were encountered: