Stream: git-wasmtime

Topic: wasmtime / issue #2979 Async functions and boxing


view this post on Zulip Wasmtime GitHub notifications bot (Jun 12 2021 at 15:25):

bkolobara opened issue #2979:

I'm working on switching Lunatic's implementation from async-wormhole to use Wasmtime's native async support.

I noticed that all async functions must return a boxed Future (e.g. Box<dyn Future<Output = Result<(), Trap>> + Send + 'a>). And I'm just worried that doing a heap allocation on every call to a host function will be a bit too much overhead.

In async-wormhole I just pin the Future to the fiber stack (that I know will not move) to avoid this. It also resulted in a bit better ergonomics. I was wondering if a similar approach would be possible for Wasmtime's async function definitions.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 12 2021 at 17:37):

alexcrichton commented on issue #2979:

This is an unfortunate limitation in Rust right now which I believe forces us to box up these futures. If it weren't for this limitation, though, we would have no need for boxing and we could indeed just pin the futures to the stack and that'd work just fine.

The problem in Rust is from the signature, which I'll shorten here a bit:

F: for<'a> Fn(Caller<'a, T>) -> Box<dyn Future<Output = ()> + 'a>

Here we specifically want the future returned to close over the 'a lifetime that the Caller is connected to, and I think that this is the only signature that allows that. This signature for example:

F: for<'a> Fn(Caller<'a, T>) -> U,
U: Future<Output = ()>

doesn't connect the 'a to the U, so U can't close over the 'a. Other various combinations don't work out as well (or at least from what I've tried).

I think this is just a limitation of Rust's type system. I'm not really sure if there's a feature that would solve this on the horizon (like GATs or something similar), and I haven't dug too deeply into figuring out if we should report this upstream.

The hope with these APIs was that the allocation wouldn't be an issue in that it's only once and in theory if something async is happening the async yield takes far more time. That being said if this is a problem and the cost is too high then the next steps would probably be to dive into the specifics of your use case and see if there's an alternative solution with less cost.

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 16:32):

alexcrichton commented on issue #2979:

I'm going to close this issue because I don't believe that Rust offers a solution for us to fix this at this time. If this becomes a significant bottleneck though we can try to investigate other routes as well, although at this time I'm not actually sure what those other routes would be.

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 16:32):

alexcrichton closed issue #2979:

I'm working on switching Lunatic's implementation from async-wormhole to use Wasmtime's native async support.

I noticed that all async functions must return a boxed Future (e.g. Box<dyn Future<Output = Result<(), Trap>> + Send + 'a>). And I'm just worried that doing a heap allocation on every call to a host function will be a bit too much overhead.

In async-wormhole I just pin the Future to the fiber stack (that I know will not move) to avoid this. It also resulted in a bit better ergonomics. I was wondering if a similar approach would be possible for Wasmtime's async function definitions.


Last updated: Oct 23 2024 at 20:03 UTC