Stream: git-wasmtime

Topic: wasmtime / PR #3345 Add a new `Func::wrap_cabi` API


view this post on Zulip Wasmtime GitHub notifications bot (Sep 13 2021 at 18:05):

alexcrichton opened PR #3345 from add-c-api-func-wrap to main:

This commit adds a new API to the wasmtime::Func type for wrapping a
C-ABI function with a well-defined signature derived from a wasm type
signature. The purpose of this API is to add the-most-optimized-we-can
path for using the C API and having wasm call host functions. Previously
when wasm called a host function it would perform these steps:

  1. Using a trampoline, place all arguments into a u128* array on the
    stack.

  2. Call Func::invoke which uses the type of the function (dynamically)
    to read values from this u128*.

  3. Values are placed within a Vec<Val> after being read.

  4. The C API receives &[Val] and translates this to
    &[wasmtime_val_t], iterating over each value and copying its
    contents into a new vector.

  5. Then the host function is actually called.

  6. The above argument-shuffling steps are all performed in reverse for
    the results, shipping everything through wasmtime_val_t and Val.

PRs such as #3319 and related attempts have made this sequence faster,
but the numbers on #3319 show that even after we get all the allocation
and such bits out of the way we're still spending quite a lot of time
shuffling arguments back-and-forth relative to the Func::wrap API that
Rust can use.

This commit fixes the issue by eliminating all steps except 1/5 above.
Although we still place all arguments on the stack and read them out
again to call the C-defined function with it's much faster than pushing
this all through the Val and wasmtime_val_t machinery. This overall
gets the cost of a wasm->host call basically on-par with Func::wrap,
although it's still not as optimized. Benchmarking the overhead of
wasm->host calls, where i64 returns one i64 value and many takes 5
i32 parameters and returns one i64 value, the numbers I get are:

Import Rust C before C after
i64 1ns 40ns 7ns
many 1ns 91ns 10ns

This commit is a clear win over the previous implementation, but it's
even still somewhat far away from Rust. That being said I think I'm out
of ideas of how to make this better. Without open-coding much larger
portions of wasmtime I'm not sure how much better we can get here. The
time in C after this commit is almost entirely spent in trampolines
storing the arguments to the stack and loading them later, and at this
point I'm not sure how much more optimized we can get than that since
Rust needs to enter the picture here somehow to handle the Wasmtime
fiddly-bits of calling back into C. I'm hopeful, though, that this is
such a large improvement from before that the question of optimizing
this further in C is best left for another day.

The new Func::wrap_cabi method is unlikely to ever get used from Rust,
but a wasmtime_func_wrap API was added to the C API to mirror
Func::wrap where if the host function pointer has a specific ABI this
function can be called instead of wasmtime_func_new.

<!--

Please ensure that the following steps are all taken care of before submitting
the PR.

Please ensure all communication adheres to the code of conduct.
-->

view this post on Zulip Wasmtime GitHub notifications bot (Sep 13 2021 at 18:15):

alexcrichton updated PR #3345 from add-c-api-func-wrap to main.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 13 2021 at 19:58):

alexcrichton updated PR #3345 from add-c-api-func-wrap to main.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 13 2021 at 20:10):

alexcrichton updated PR #3345 from add-c-api-func-wrap to main.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 14 2021 at 20:18):

alexcrichton closed without merge PR #3345.


Last updated: Dec 23 2024 at 12:05 UTC