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

Add a new Func::wrap_cabi API #3345

Closed

Commits on Sep 13, 2021

  1. Add a new Func::wrap_cabi API

    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 bytecodealliance#3319 and related attempts have made this sequence faster,
    but the numbers on bytecodealliance#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`.
    alexcrichton committed Sep 13, 2021
    Configuration menu
    Copy the full SHA
    9c19f96 View commit details
    Browse the repository at this point in the history
  2. Fix lightbeam

    alexcrichton committed Sep 13, 2021
    Configuration menu
    Copy the full SHA
    4cf546a View commit details
    Browse the repository at this point in the history
  3. Fix some tests

    alexcrichton committed Sep 13, 2021
    Configuration menu
    Copy the full SHA
    e302d5a View commit details
    Browse the repository at this point in the history
  4. Fix a doctest

    alexcrichton committed Sep 13, 2021
    Configuration menu
    Copy the full SHA
    77f035e View commit details
    Browse the repository at this point in the history