Apologies if this is double posting. I am new to Zulip. I tried posting this in wasmtime, but then it vanished (and I can't see it), so I'm not sure if the post went through or not.
I have a question regarding https://docs.rs/wasmtime-fiber/latest/wasmtime_fiber/struct.Suspend.html#method.suspend
Thanks!
FWIW the wasmtime-fiber
crate is a low-level library that isn't intended necessarily to be used as a general purpose crate. It's primarily there to enable Wasmtime's async implementation.
That being said the solution it provides for Wasmtime is the ability to suspend a WebAssembly computation by capturing its native stack. The fiber itself calls suspend to return control flow to the original thread which started the fiber and then the fiber can be resumed at a later time
This topic was moved here from #general > wasmtime_fiber by fitzgen (he/him).
Sorry if I am missing something very basic. Is there a way to use wasmtime-fiber as follows:
I see the wasmtime-fiber crate; I see the wasmtime fuel functions. It is not obvious to me how to use the two together.
Users of the wasmtime
crate don't use wasmtime-fiber
at all, it's just an internal implementation detail. Everything is handled for you when using async in Wasmtime
I want to build a toy version of Beam / Lunatic, but with wasmtime as the 'lightweight' processes.
Looking at https://docs.wasmtime.dev/api/wasmtime/struct.Store.html#method.fuel_async_yield_interval this seems a bit too high level, as it auto re-marks self as "to run"
I want a system where I can
In particular, I want this low level control where when something runs out of fuel, it notifies "me" (my code); my code puts it on some queue, at some later point adds it more fuel, and tells it to re-run.
I want to control the logic of after "wasmtime out of fuel, suspended" to "wasmtime added fuel, rerun"
whereas the existing logic seems to just auto re-subscribe self to re-run.
In particular, neither https://docs.rs/wasmtime/latest/wasmtime/struct.Store.html#method.out_of_fuel_trap (kills wasmtime on out of fuel)
nor
https://docs.rs/wasmtime/latest/wasmtime/struct.Store.html#method.out_of_fuel_async_yield (auto refills wasmtime on out of fuel, then kills it after refills done)
does what I want
I am looking for something where I can say:
the existing primitives seems to auto-refill everything and let the async runtime sort out who runs what
I want a bit more manual control
and if I use https://docs.rs/wasmtime/latest/wasmtime/struct.Store.html#method.epoch_deadline_callback it forces me then & there to decide whether to kill or refill a wasmtime
instead, I'd prefer to say: "I'm going to throw this suspended wasmtine on a queue, and at some later point, figure out whether to kill it / refill it and rerun / ..."
I think you could probably get the effect you're looking for with a custom Future
wrapper though it may be a little tricky depending on exactly what you're trying to accomplish. You could effectively "pause" execution by returning Poll::Pending
from the wrapper's Future::poll
and arranging for a wakeup based on your own logic. One hiccup is that I believe you wouldn't be able to easily control fuel/epoch refilling outside of the existing methods available as the inner Future would hold a &mut Store
.
It also wouldn't be too hard to add an out-of-fuel callback similar to how epochs have a custom callback as well
Are you referring to https://docs.rs/wasmtime/latest/wasmtime/struct.Store.html#method.epoch_deadline_callback and https://docs.rs/wasmtime/latest/wasmtime/enum.UpdateDeadline.html
The problem I see there is that it demands, at the moment that it runs out of fuel, that I immediately decided what to do with it: kill, continue, or yield (which says "rerun, at the async runtime's convenience").
I'm looking for something where the callback gets something (say, like a Rc<RefCell<wasmtime-fiber>>
) which it can throw onto a queue, and deal with it later.
in Rust, the value you get to manipulate with a suspended async computation is called a Future (probably a Pin<Box<dyn Future>>)
and when the epoch deadline callback returns a Yield, that means the Future currently executing wasm will return a Poll::Pending
so, execution will be suspended until you again call Future::poll
on that Future.
Yes the callback would be combined with what Lann mentioned above where you might have a wrapper around Future for doing the enqueueing you're desiring
using the pending signal Pat's talking about
@Pat Hickey : I am familiar with Rust + async Rust. I am not (yet) familiar with the wasmtime api. It looks like I am misunderstanding something.
Atter an epoch deadline callback, to resume the wasmtime "lightweight process", I call a foo.await
right? Where/how do I get this foo
?
go re-familiarize yourself with async rust. foo is a future, and the .await
on it is a call to future::poll.
I think you misunderstood my question.
Here is the function
pub fn epoch_deadline_callback(
&mut self,
callback: impl FnMut(StoreContextMut<T>) -> Result<UpdateDeadline> + Send + Sync + 'static,
) {
self.inner.epoch_deadline_callback(Box::new(callback));
}
https://docs.rs/wasmtime/latest/src/wasmtime/store.rs.html#935-940
So now my question is: for us to call foo.await
, we need a foo
-- but our callback gets a https://docs.rs/wasmtime/latest/wasmtime/struct.StoreContextMut.html .
Where do we get the FUTURE from ?
Function::call_async
and friends return a Future
. that is the future that will return Pending when the epoch causes it to yield
I think this clarifies everything up. I will test out some code. Thanks!
zeroexcuses has marked this topic as resolved.
Last updated: Dec 23 2024 at 14:03 UTC