当我在 WebAssembly 中声明内存部分时,我必须设置初始大小,并且可以设置可选的最大大小。
如果我将最大值设置为与初始值相同的值,它有什么优势吗?这个值对 WebAssembly 运行时有什么影响?
背景:我编写了一个Java 到 WebAssembly 编译器,并希望对我的数据使用即将到来的 GC 功能。我不需要增加记忆。我只会将它用于常量值。
当我在 WebAssembly 中声明内存部分时,我必须设置初始大小,并且可以设置可选的最大大小。
如果我将最大值设置为与初始值相同的值,它有什么优势吗?这个值对 WebAssembly 运行时有什么影响?
背景:我编写了一个Java 到 WebAssembly 编译器,并希望对我的数据使用即将到来的 GC 功能。我不需要增加记忆。我只会将它用于常量值。
分配大内存(尤其是千兆字节时)可能会失败。未能分配初始内存是致命错误,而未能增加内存则不是。因此,从较小且安全的初始大小开始是个好主意。
WebAssembly 社区已经提供了非常好的文档:
我将在这里总结有关 WebAssembly 内存如何工作的信息。
底层WebAssembly 内存是一个JS ArrayBuffer对象。ArrayBuffer 不是动态数组,这意味着它不能调整大小。但是,Wasm Memory 是一个特殊的 ArrayBuffer,可以通过Memory.grow()调用来调整大小,这与grow_memory
Wasm 中的指令相对应。尽管如此,调整 ArrayBuffer 大小的实现成本很高 - 它与 相同realloc()
,它分配一个具有新大小的新缓冲区,然后释放旧缓冲区。您可以通过分配大的初始内存来避免重新分配缓冲区的开销,但它会导致另一个问题,即操作可能会失败并且失败意味着 Wasm 引擎无法加载 Wasm 二进制文件。
可选的最大尺寸解决了这些问题。定义最大大小后,Wasm 内存会尝试预先分配缓冲区的最大大小。通过预先分配缓冲区,您可以稍后调整缓冲区的大小,而无需进行昂贵的realloc()
操作。即使预分配操作失败也没关系 - 您可以稍后在需要时尝试重新分配。
grow_memory
没有设置最大大小:Wasm 引擎尝试重新分配整个缓冲区,这非常昂贵并且增加了失败的可能性。grow_memory
最大大小:引擎将立即使用预分配的缓冲区。即使它未能增长,也不是致命错误。