I have a WASM binary that receives a url to download and a file path to store the downloaded data to. It also only has access to both these resources and otherwise is fully sandboxed.
My program needs to download a large amount of files (100,000) and I want to make this as fast as possible. In pure Rust, I have used futures::stream
and buffered_unordered
to do the downloading in parallel.
Can I do the same using my WASM binary? Instead of using a Rust HTTP library, I want to instantiate my WASM binary and run it for a given URL. What is the best way to reduce overall overhead?
Since each instantiated and running module has different permissions, it seems that I have to re-link them every single time. Which seems to be a big overhead performance-wise.
My current Rust code is based on this blogpost: https://patshaughnessy.net/2020/1/20/downloading-100000-files-using-async-rust
For parallel execution, you'll need to instantiate the component multiple times and invoke each instance in a separate thread (or Tokio task). For concurrent execution, buffer_undordered
works just fine, as this example illustrates: https://github.com/bytecodealliance/wasmtime/blob/main/crates/test-programs/src/bin/api_proxy_streaming.rs
side note: you can instantiate_pre the component which greatly reduces the overhead when running multiple instances of the same component
Thanks for the replies!
I am confused about the usage together with Preview2 of WASI though. Since that requires me to create a new store for each module and thus each module has to get instantiated again (AFAIK).
https://docs.wasmtime.dev/examples-rust-wasi.html#async-example
the instantiate_pre methods all return an InstancePre object, InstancePre executes as much as possible, you only add a store for each instance you want, the main cpu intensive part of instantiating only needs to be done once
https://docs.rs/wasmtime/latest/wasmtime/component/struct.Linker.html#method.instantiate_pre
Besides using instantiate_pre
, you can also reuse instances (and their stores) for multiple invocations. I.e. you only need to create as many instances as you have cores, and then you can invoke exports on those instances as many times as you like, passing as much work (i.e. as many URLs) as you like to each invocation.
Last updated: Dec 23 2024 at 13:07 UTC