我写了一些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`);