Stream: wasmtime

Topic: About core module vs component call performance


view this post on Zulip ghh (Aug 25 2026 at 15:25):

Hello, I'm new to WASM and the Component Model, sorry if I'm asking something obvious or the terminology is wrong.

I got curious about the overhead that WASM function calls carry, so I wrote some microbenchmarks to test this: cdylib calls (just for comparison), WASM core module calls (wasm32-unknown-unknown) and WASM component (wasm32-wasip2) calls. For each type host-to-guest and host-to-guest-to-host calls are tested, and the functions just add two arguments. The repo: https://github.com/Bamberghh/wasm-bench-test. Here's the results for my machine:

// Dynamic library call
rust_to_cdylib                 time:   [1.6834 ns 1.6853 ns 1.6874 ns]
rust_to_cdylib_to_rust         time:   [2.6480 ns 2.6505 ns 2.6532 ns]
// WASM core module call
rust_to_wasm_module            time:   [26.853 ns 26.899 ns 26.950 ns]
rust_to_wasm_module_to_rust    time:   [33.701 ns 33.754 ns 33.808 ns]
// WASM component call
rust_to_wasm_component         time:   [669.40 ns 670.67 ns 672.01 ns]
rust_to_wasm_component_to_rust time:   [894.75 ns 896.21 ns 897.69 ns]

While I do understand why calling WASM is slower than calling a native dynamic library, I don't understand why it's much (~25x) slower to call a WASM component compared to calling a core module. Don't the functions in both types of WASM code do the same thing? Maybe I'm benchmarking this wrong, or maybe benchmarking these small calls is irrelevant? Is this difference less major the case of WASM functions doing more work?

view this post on Zulip Chris Fallin (Aug 25 2026 at 16:12):

The component cost is much higher than it should be; @Adam Bratschi-Kaye (he) just landed an optimization to this and could probably say more about what he has seen in profiling. Note also that disabling concurrency support (the new-style native async within WIT) speeds things up considerably right now

view this post on Zulip Adam Bratschi-Kaye (he) (Aug 25 2026 at 16:45):

Maybe I'm benchmarking this wrong, or maybe benchmarking these small calls is irrelevant?

Those numbers look pretty close to what I was getting. I think if you disable concurrency with this config as Chris mentioned you should speed up the component calls by ~50% (at the cost of being able to use WASIp3 APIs).

Don't the functions in both types of WASM code do the same thing?

Yes, but with the component model there's more setup that the engine needs to do before it can actually enter the Wasm code. Some examples are allocating a CallContext to manage the lifetimes of borrows passed to the call, and ResourceTables for managing component model resources which might be needed during the call. Also with the async component model there's additional work to set up the runtime which manages guest tasks and allocation of the task for this specific call.

view this post on Zulip Adam Bratschi-Kaye (he) (Aug 25 2026 at 16:47):

I'm planning to look into this more and see if we can get the component model overhead closer to core Wasm, so definitely let me know if you come across anything interesting or have any suggestions!

view this post on Zulip fitzgen (he/him) (Aug 25 2026 at 16:47):

fwiw, these costs are mostly only paid on the host --> wasm call boundary, not wasm --> wasm or wasm --> host

but yeah, there is ongoing work to improve things here


Last updated: Aug 30 2026 at 09:07 UTC