Stream: git-wasmtime

Topic: wasmtime / PR #14189 wasmtime: Cache `VMFuncRef` in `comp...


view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2026 at 19:00):

adamrk opened PR #14189 from adamrk:cache-component-funcref to bytecodealliance:main:

A core Func caches a raw pointer to its VMFuncRef, but a
component::Func rederives the pointer on ever call and this
contributes to host -> wasm component function calls having
significantly higher overhead than core function calls (even concurrency
support disabled).

This PR caches the VMFuncRef for component::Func in the same it is
currently done for core Func. The VMFuncRef for the associated
post_return call is also cached along with Some additional metadata.

These are my benchmark results for the impact on nop calls with no
arguments or return values:

Before change:

| Call type                         | Latency |
-----------------------------------------------
| core                              |   35 ns |
| component (concurrency disabled)  |  300 ns |
| component (concurrency enabled)   |  800 ns |

After change:

| Call type                         | Latency |
-----------------------------------------------
| core                              |   35 ns |
| component (concurrency disabled)  |  140 ns |
| component (concurrency enabled)   |  600 ns |

The bencmarks run are:

cargo bench --bench call -- --exact "sync/no-hook/core - host-to-wasm - typed - nop"
cargo bench --bench call -- --exact "no-concurrent/sync/no-hook/component - host-to-wasm - typed - nop"
cargo bench --bench call -- --exact "concurrent/sync/no-hook/component - host-to-wasm - typed - nop"

A separate commit also modifies the call benchmark to allow running component calls without concurrency support.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2026 at 19:00):

adamrk requested pchickey for a review on PR #14189.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2026 at 19:00):

adamrk requested wasmtime-core-reviewers for a review on PR #14189.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2026 at 19:00):

adamrk requested alexcrichton for a review on PR #14189.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2026 at 19:00):

adamrk requested wasmtime-default-reviewers for a review on PR #14189.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2026 at 21:48):

github-actions[bot] added the label wasmtime:api on PR #14189.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2026 at 21:48):

github-actions[bot] added the label wasmtime:c-api on PR #14189.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 14:10):

:memo: adamrk submitted PR review.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 14:10):

:speech_balloon: adamrk created PR review comment:

Note: This change to the benchmark was required to bench component calls with concurrency_support disabled. The previous setup would only run them with it enabled.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 14:10):

:speech_balloon: adamrk created PR review comment:

Note: I think we could also save a lookup here by caching CanonicalOptions as well, but I didn't do it because that type has a bunch of fields and variants which I think would require either

  1. Making the C type messy and changing it whenever new canon opts are made. Or
  2. Boxing CanonicalOptions before storing it in Func.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 15:06):

alexcrichton unassigned pchickey from PR #14189 wasmtime: Cache VMFuncRef in component::Func.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 15:09):

:memo: alexcrichton submitted PR review:

Nice wins! Do you have a relative breakdown of where the wins are coming from? For example which lookup is the most expensive?

I'm a bit wary to inflate component::Func too too much to avoid duplicating information thoughout the runtime, so if some of the field movements are pretty minor in wins and one field predominantly dominates that might be a way to cut down on duplication. Naively for example I'd expect that ExportIndex would be relatively quick to lookup the type/options, and then the presence of post-return and async-ness in theory not too much more expensive when looking up the options themselves. Basically I'd expect that the unsafe_func_ref field to be the majority of the win here, but before actually changing anything here I'd want to confirm about where the performance wins come from

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 15:19):

adamrk commented on PR #14189:

Do you have a relative breakdown of where the wins are coming from? For example which lookup is the most expensive?

I didn't do a breakdown, but I can get one. Also I'm now realizing that abi_info gets called a few times, so maybe even if we don't include other fields in Func we can at least get some improvement by just calling abi_info once and reusing the result.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 20:56):

adamrk commented on PR #14189:

For the case of concurrency disabled, with just the unsafe_func_ref field I'm seeing a time of 180ns (from the 300ns original). So all the other fields together are an additional ~40ns. It's a bit hard to divide up the remaining amount between specific other fields because I'm seeing 10-20ns swings between runs anyway.

I also realized we could mostly reuse the results of abi_info in the non-concurrent case without caching them in Func and that seems to give us most of the benefits anyway. With the existing changes I'm now seeing 140ns with concurrency disabled (same as the original change) and 730ns with concurrency enabled (not as big as the original change).

I guess this means we could just use the unsafe_func_ref field and there's probably opportunity to improve the concurrent case as a follow up by reusing the results of abi_info more.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 20:57):

adamrk updated PR #14189.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 22:05):

:thumbs_up: alexcrichton submitted PR review:

Sounds reasonable to me, and changes look good!

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 22:06):

alexcrichton added PR #14189 wasmtime: Cache VMFuncRef in component::Func to the merge queue

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 22:32):

:check: alexcrichton merged PR #14189.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 24 2026 at 22:32):

alexcrichton removed PR #14189 wasmtime: Cache VMFuncRef in component::Func from the merge queue


Last updated: Aug 30 2026 at 09:07 UTC