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

Allow multiple instances of the same named import (e.g. javy_quickjs_provider_v2) #2294

Closed
bep opened this issue Jul 29, 2024 · 5 comments · Fixed by #2298
Closed

Allow multiple instances of the same named import (e.g. javy_quickjs_provider_v2) #2294

bep opened this issue Jul 29, 2024 · 5 comments · Fixed by #2298
Labels
enhancement New feature or request

Comments

@bep
Copy link
Contributor

bep commented Jul 29, 2024

Is your feature request related to a problem? Please describe.

This is a more concrete follow up to #2293. Currently it's only possible to have one instance of a named import, so if you want multiple instances that requires the same import, you need to create multiple runtimes.

Describe the solution you'd like

I guess there are many ways to go about this, one way could possibly be a new module config option, e.g.

namedImports := map[string]api.Module{
   "javy_quickjs_provider_v2", myQuickJsInstance,
}
wazero.NewModuleConfig().WithNamedImports(namedImports)

Describe alternatives you've considered

I tested out 2 options:

  1. One runtime per script (with a shared compilation cache)
  2. Having the QuickJS runtime embedded in the JS script wasm.

The benchmark below shows the two options compared. The motivation in the case below is speeding up the relatively slow Katex by throwing more threads at it, but different scripts needing the QuickJS import will end up with the same problem.

Embedding the QuickJS runtime makes the startup much more effective, but

  1. The wasm files gets much larger (katex.wasm from 450 kb to 4.5 MB)
  2. It makes it very unpractical if we want to embed the QuickJS runtime and have end users provide their plugin wasm files.
name                          old time/op    new time/op    delta
KatexStartStop/PoolSize1-10     19.2ms ± 6%    20.8ms ± 5%     ~     (p=0.057 n=4+4)
KatexStartStop/PoolSize8-10      116ms ± 4%      23ms ± 3%  -80.16%  (p=0.029 n=4+4)
KatexStartStop/PoolSize16-10     222ms ± 3%      32ms ± 5%  -85.58%  (p=0.029 n=4+4)

name                          old alloc/op   new alloc/op   delta
KatexStartStop/PoolSize1-10     12.2MB ± 0%    11.4MB ± 0%   -7.01%  (p=0.029 n=4+4)
KatexStartStop/PoolSize8-10     97.9MB ± 0%    49.5MB ± 0%  -49.43%  (p=0.029 n=4+4)
KatexStartStop/PoolSize16-10     196MB ± 0%      93MB ± 0%  -52.46%  (p=0.029 n=4+4)

name                          old allocs/op  new allocs/op  delta
KatexStartStop/PoolSize1-10      18.1k ± 0%     25.8k ± 0%  +42.74%  (p=0.029 n=4+4)
KatexStartStop/PoolSize8-10       144k ± 0%       32k ± 0%  -77.61%  (p=0.029 n=4+4)
KatexStartStop/PoolSize16-10      289k ± 0%       40k ± 0%  -86.20%  (p=0.029 n=4+4)
@bep bep added the enhancement New feature or request label Jul 29, 2024
@mathetake
Copy link
Member

@bep thanks for the proposal. Are you in the Gophers slack? There's a relatively large community in #wazero channel and I think if you share your thoughts there, people there might hop into the discussion with you.

@bep
Copy link
Contributor Author

bep commented Aug 1, 2024

@mathetake I feel the discussion on Slack is drifting away from the problem at hand. I need some kind of conclusion on this to decide if I can continue down this path or if I need to look at alternatives.

Would a PR with this new config option be a likely merge if done properly (with tests et all)?

namedImports := map[string]api.Module{
   "javy_quickjs_provider_v2", myQuickJsInstance,
}
wazero.NewModuleConfig().WithNamedImports(namedImports)

@mathetake
Copy link
Member

wazero never breaks API which is our promise, so I won't accept in the public API (except experimental/ package) until multiple people actually start using it. At best at this point, under experimental package would be the way, but I am still not convinced if that's really necessary as per the discussion in slack.

@mathetake
Copy link
Member

having said that, I think if that's in experimental, I am ok with it for now

@bep
Copy link
Contributor Author

bep commented Aug 2, 2024

OK, so with the help of the people in the Wazero Slack channel, we got to the bottom of my main performance problem of this, to summarise for others scratching their heads about the same:

  • With the compile cache set on the runtime you still end up doing lot of work (about 10ms per cached compilation in my case).
  • The return of Runtime.CompileModule isn't scoped to the runtime even if the method placement suggests so and the GoDoc does not mention it.
  • This makes it possible to implement a local cache (e.g. map[string]wasi.Module) and work around most of the performance issues.

My benchmarks still suggests that having a runtime per instance is more (memory) costly and it feels unneedingly clunky, so I still think my suggestion above, simple as it is, makes sense to add.

bep added a commit to bep/wazero that referenced this issue Aug 3, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 3, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 3, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 3, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 3, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 4, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 4, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 4, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 5, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294
bep added a commit to bep/wazero that referenced this issue Aug 5, 2024
If set in context, the ImportResolver will be used as the first step in resolving imports.

Closes tetratelabs#2294

Signed-off-by: Bjørn Erik Pedersen <[email protected]>
bep added a commit to bep/wazero that referenced this issue Aug 5, 2024
Compile once and reuse.

See tetratelabs#2294

Signed-off-by: Bjørn Erik Pedersen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants