我应该什么时候调用wasm-pack生成的free()方法



我写了一些Rust代码,并用wasm包编译了它。我在生成的.d.ts文件中注意到这些free()方法:

export class PdfDoc {
free(): void;
...
}

PdfDoc拥有大量的内存,高达1GB,因此在javascript代码完成后,正确释放所有内存以供重用是很重要的

问题:

  • 我应该何时调用这些free()方法
  • 我需要显式调用它们吗?还是会自动调用它们
  • 如果我从不给他们打电话会怎样

我搜索了";wasm无包装方法";但这些搜索词的组合并没有发现任何有用的东西。

我也在想同样的事情:当使用wasm-bindgen时,我需要仔细地将每个new MyStruct()与对free()的调用配对吗?

我应该什么时候调用这些free((方法?

在丢失对JS对象包装器实例的最后一个引用之前调用free(),如果您已经使用完该对象,则可以更早调用。

我需要显式调用它们还是会自动调用它们?

当前,当JS对象包装器超出范围时,WASM分配的内存将不会释放(但下面的s.a.弱引用(。

如果我从不给他们打电话,会发生什么?

WASM内存丢失,如果没有指针,现在您将无法恢复它。对于固定或有限数量的较小结构,这可能不是问题,整个WASM内存在卸载页面时释放。

详细信息:

查看创建的绑定,我们可以看到在构造函数中分配的内存不会在其他地方被跟踪,如果我们忘记返回的实例(一个将原始指针存储为ptr的JS包装器对象(,则内存实际上会丢失。

wasm-bindgen指南在支持弱引用中也提示了这一点提到目前(2022年末(不支持/实施TC39弱引用:

如果没有弱引用,您的JS集成可能容易受到Rust中内存泄漏的影响,例如:您可能会忘记对JS对象调用.free((,从而分配Rust内存。

wasm-bindgen指南示例WebAudio显示了使用free()来防止重复创建超出范围的对象时内存泄漏。最多只剩下一个(活动(对象,它主要反映了您的用例:在不再需要对象时以及对象超出范围之前,通过调用free()来清理对象。

作为谨慎内存管理的附加说明:

在使用复制类型时,可能需要注意一个设计问题,请考虑:

#[wasm_bindgen]
#[derive(Clone, Copy)]
pub struct Bounds {
width: usize,
height: usize,
}
#[wasm_bindgen]
impl Bounds {
// ...
#[wasm_bindgen(getter)]
pub fn width(&self) -> usize {
self.width
}
}
#[wasm_bindgen]
pub struct MyThing {
bounds: Bounds,
// ...
}
#[wasm_bindgen]
impl MyThing {
// ...
#[wasm_bindgen(getter)]
pub fn bounds(&self) -> Bounds {
self.bounds
}
}

这是Rust中常见且安全的代码,但如果只是从JS(如(中使用,这里会泄漏内存

console.log(`Current width is ${myThing.bounds.width} px`);

在使用等进行开发时,您可能需要查看WASM内存

console.log(`WASM memory usage is ${wasm.memory.buffer.byteLength} bytes`);

最新更新