Stream: git-wasmtime

Topic: wasmtime / issue #10868 Memory "leak" when passing funcre...


view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 15:31):

alexcrichton opened issue #10868:

This program:

use wasmtime::*;

fn main() -> Result<()> {
    let engine = Engine::default();
    let mut store = Store::new(&engine, ());

    let module = Module::new(
        &engine,
        r#"
            (module
                (import "" "" (func (param funcref)))

                (elem declare func $x)

                (func $x)
                (func (export "")
                    ref.func $x
                    call 0)
            )
        "#,
    )?;

    let func = Func::wrap(&mut store, |_: Option<Func>| {});
    let i = Instance::new(&mut store, &module, &[func.into()]).unwrap();
    let f = i.get_typed_func::<(), ()>(&mut store, "")?;
    loop {
        f.call(&mut store, ())?;
    }
}

will infinitely consume memory until killed. Basically what happens here is that each time a host function with a funcref parameter is invoked Wasmtime creates a new Func which pushes onto an internal store-local vector that is never shrunk. That means that the memory usage of a store is O(calls) which is generally not a desirable property we want to have.

This is not a regression but is something that's been around for quite a long time. I'm working on fixes in this area though and wanted to file an issue about this.

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 15:31):

alexcrichton added the wasmtime:api label to Issue #10868.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 03 2025 at 00:18):

alexcrichton closed issue #10868:

This program:

use wasmtime::*;

fn main() -> Result<()> {
    let engine = Engine::default();
    let mut store = Store::new(&engine, ());

    let module = Module::new(
        &engine,
        r#"
            (module
                (import "" "" (func (param funcref)))

                (elem declare func $x)

                (func $x)
                (func (export "")
                    ref.func $x
                    call 0)
            )
        "#,
    )?;

    let func = Func::wrap(&mut store, |_: Option<Func>| {});
    let i = Instance::new(&mut store, &module, &[func.into()]).unwrap();
    let f = i.get_typed_func::<(), ()>(&mut store, "")?;
    loop {
        f.call(&mut store, ())?;
    }
}

will infinitely consume memory until killed. Basically what happens here is that each time a host function with a funcref parameter is invoked Wasmtime creates a new Func which pushes onto an internal store-local vector that is never shrunk. That means that the memory usage of a store is O(calls) which is generally not a desirable property we want to have.

This is not a regression but is something that's been around for quite a long time. I'm working on fixes in this area though and wanted to file an issue about this.


Last updated: Dec 06 2025 at 06:05 UTC