如何释放由暴露在 WebAssembly 中的 Rust 代码分配的内存?

How can I free memory allocated by Rust code exposed in WebAssembly?

我有一个用 Rust 和 wasm-bindgen 编写的 Web 应用程序需要存储状态。状态是这样存储的:

lazy_static! {
    static ref ID_TO_DATA: Mutex<HashMap<u32, Data>> = Mutex::new(HashMap::new());
}

pub struct Data {
    pub coder_id: u16,
    pub bools: Vec<bool>,
    pub ints: Vec<i32>,
    pub strings: Vec<String>,
}

我尝试了以下操作来删除数据并释放内存,并且数据已从 HashMap 中删除并且未报告任何错误:

#[wasm_bindgen]
pub fn remove_data(id: u32) {
    match ID_TO_DATA.lock().unwrap().remove(&id) {
        Some(data) => {
            std::mem::drop(data);
        }
        None => {}
    }
}

但是,浏览器选项卡使用的内存永远不会下降(使用 Chrome 67)。我使用 Windows' 任务管理器,看到相关 process/tab 的内存增长到将近 2GB,然后在我的程序删除所有条目后,我等了一分钟,内存仍然接近 2GB。

我也尝试了以下方法,但出现此错误:RuntimeError: memory access out of bounds

#[wasm_bindgen]
pub fn remove_data(id: u32) {
    match ID_TO_DATA.lock().unwrap().remove(&id) {
        Some(mut data) => {
            unsafe {
                std::ptr::drop_in_place(&mut data);
            }
        }
        None => {}
    }
}

如何才能成功释放此内存?

WebAssembly does not offer any instructions to deallocate memory,只能增加分配的大小。实际上,这意味着您的 WebAssembly 应用程序的峰值内存使用量也是 永久 内存使用量。

对于给定的问题,可以调整您的算法以减少内存的峰值。

我没有知识或能力来测试这个,但一个开箱即用的想法是尝试让多个 WebAssembly 运行时彼此不同。你可以在一个中消耗大量内存来计算一个相对较小的结果,在 WASM 运行时之外序列化该结果,然后将其丢弃并启动一个新的。这可能只对某些特定的问题领域有用。


将来,内存大小调整可能会重新添加到 WebAssembly。它在 MVP 发布之前被明确删除:

After the MVP, we are moving to things that diverge and cannot be polyfilled, and memory resizing makes more sense to add at that point in time.

感谢 alexcrichton and steveklabnik 在 Rust Discord 中回答这个问题。