Stream: git-wasmtime

Topic: wasmtime / issue #13338 How to add fuel when yielding exe...


view this post on Zulip Wasmtime GitHub notifications bot (May 11 2026 at 22:48):

AngelicosPhosphoros opened issue #13338:

I have a question about using fuel in conjuction with

Scenario: suppose we run some long-running calculation but want to let a guest only use some amount of fuel before interruption and continue in some future (imagine running a WASM plugin for a game engine that compute something in the background and we let the computation progress for 1000 fuel in each event loop iteration).

How can we achieve that?

Documentation suggests using Store::set_fuel for that, but it is not possible because the Store is mutably borrowed by the asynchronous guest call until it finishes, and it finishes when the computation is finished.

So I do not understand how I can add fuel to ongoing computation between yields.

Example of my code for now:

use wasmtime::component::{Component, Linker};
use wasmtime::{Config, component};
use wasmtime::{Engine, Store};

use crate::nbody::Output;

component::bindgen!({
    world: "the-world",
    inline: "
        package nbody:nbody@0.1.0;
        interface nbody-calc {
            record output {
                original: f64,
                final: f64,
            }
            compute: func(steps: u32) -> output;
        }
        world the-world {
            export nbody-calc;
        }
    ",
    exports: {
        default: async,
    }
});

const WASM_BYTES: &[u8] = include_bytes!("../../target/wasm32-wasip2/release/nbody_rs.wasm");

#[must_use]
#[allow(clippy::missing_panics_doc)] // hardcoded wasm
pub fn wasm_prepare() -> (Store<()>, TheWorld) {
    let mut config = Config::new();
    config.consume_fuel(true);
    let engine = Engine::new(&config).unwrap();
    let component = Component::from_binary(&engine, WASM_BYTES).unwrap();

    let linker = Linker::new(&engine);
    let mut store: Store<()> = Store::new(&engine, ());

    let bindings: TheWorld = TheWorld::instantiate(&mut store, &component, &linker).unwrap();
    (store, bindings)
}

#[must_use]
#[allow(clippy::missing_panics_doc)] // hardcoded wasm
pub fn wasm_compute(store: &mut Store<()>, bindings: &TheWorld, steps: u32) -> Output {
    store.set_fuel(1000).unwrap();

    let res = pollster::block_on(async {
        // Where I put set_fuel(1000) to add fuel
        // in case of exhausting all fuel?
        bindings
            .nbody_nbody_nbody_calc()
            .call_compute(store, steps)
            .await
            .unwrap()
    });
    Output {
        original: res.original,
        final_: res.final_,
    }
}

view this post on Zulip Wasmtime GitHub notifications bot (May 11 2026 at 23:42):

AngelicosPhosphoros commented on issue #13338:

I think, I found the way:

pub fn wasm_compute(store: &mut Store<()>, bindings: &TheWorld, steps: u32) -> Output {
    use std::task::{Context, Poll, Wake};

    struct DummyWaker;
    impl Wake for DummyWaker {
        fn wake(self: Arc<Self>) {}
    }

    store.set_fuel(u64::MAX).unwrap();
    store.fuel_async_yield_interval(Some(1000)).unwrap();

    let mut fut = core::pin::pin!(
        the_world
            .nbody_nbody_nbody_calc()
            .call_compute(store, steps)
    );
    let res = loop {
        let waker = Arc::new(DummyWaker).into();
        let mut ctx = Context::from_waker(&waker);
        match fut.as_mut().poll(&mut ctx) {
            Poll::Ready(res) => break res,
            Poll::Pending => {
                // Can do something here.
                // Like saving the pinned future,
                // returning from a function
                // and running core event loop once
                // before returning back here.
            }
        }
    };
    let res = res.unwrap();
    Output {
        original: res.original,
        final_: res.final_,
    }
}

view this post on Zulip Wasmtime GitHub notifications bot (May 11 2026 at 23:55):

alexcrichton commented on issue #13338:

In addition to what you already have, I think epoch_deadline_callback would also solve this?


Last updated: Jun 01 2026 at 09:49 UTC