WebAssembly 中最大内存限制的含义是什么?

What are the implications of a maximum memory limits in WebAssembly?

当我在 WebAssembly 中声明一个 memory section 时,我必须设置初始大小并且我可以设置可选的最大大小。

如果我将最大值设置为与初始值相同的值是否有任何优势?这个值对 WebAssembly 运行时有什么影响?

背景:我写了一个 Java to WebAssembly compiler 并且想为我的数据使用即将到来的 GC 功能。我不需要增加内存。我只会将它用于常量值。

分配大内存(尤其是千兆字节时)可能会失败。分配初始内存失败是一个 fatal 错误,而后来增加内存失败则不是。因此,从较小且安全的初始大小开始是个好主意。

WebAssembly 社区已经提供了很好的文档:

我将在这里总结有关 WebAssembly 内存如何工作的信息。

为什么我们需要可选的最大大小

底层WebAssembly Memory is a JS ArrayBuffer object. ArrayBuffer is not a dynamic array, meaning it cannot be resized. However, Wasm Memory is a special ArrayBuffer that can be resized by Memory.grow()调用,对应Wasm中的grow_memory指令。尽管如此,调整 ArrayBuffer 大小的实现成本很高——它与 realloc() 相同,它分配一个具有新大小的新缓冲区,然后释放旧缓冲区。您可以通过分配一个大的初始内存来避免重新分配缓冲区的开销,但这会导致另一个问题,即操作可能会失败并且失败意味着 Wasm 引擎无法加载 Wasm 二进制文件。

可选的最大尺寸解决了这些问题。当定义了最大大小时,Wasm Memory 会尝试预分配缓冲区的最大大小。通过预分配缓冲区,您可以稍后调整缓冲区的大小,而无需昂贵的 realloc() 操作。即使预分配操作失败也没关系-您可以稍后在需要时尝试重新分配。

WebAssembly 内存调整场景

  • grow_memory 未设置最大大小:Wasm 引擎尝试重新分配整个缓冲区,这非常昂贵并且增加了失败的可能性。
  • 分配较大的初始内存:可能会失败,失败是致命错误。
  • grow_memory with the maximum size:引擎将立即使用预分配的缓冲区。即使增长失败也不是致命错误。
  • 设置初始大小 == 最大大小:你不会从其中任何一个中受益。它可能会遇到致命错误,你以后也不能调整它的大小。