WebAssembly 中的内存限制

Memory limits in webassembly

webassembly 程序的内存分配限制政策是什么?

是否会继承当前(硬)javascript 引擎内存限制? 例如。将有可能编写需要超过几百兆内存的实际应用程序吗?

当前关于 javascript 内存分配的浏览器策略对浏览器中实际可执行的操作构成了严格的限制。 emscripten/asm.js 和 jit 编译速度不再是问题,但内存限制使得很难或不可能在浏览器中构建任何正式的应用程序。

例如,参见 http://www.meshlabjs.net,MeshLab 网格处理系统的 运行 浏览器版本。对于桌面应用程序,主要限制是,在基于 javascript 的版本中,由于浏览器的 js 引擎对分配的固有限制,无法加载大型 3D 模型。

WebAssembly 有一个 WebAssembly.Memory object and the binary has a memory section. Through these, a developer provides educated guesses about minimum and maximum memory usage, the VM then allocates at least the minimum (or fails). A developer can then, at runtime, ask for more through grow_memory,Emscripten 等工具将在 malloc 的底层使用(它有点类似于 sbrk)。

对于 asm.js 来说,很难知道 ArrayBuffer 将如何使用,并且在一些 32 位平台上,您经常 运行 进入进程碎片,这使得它变得困难在进程的虚拟内存中分配足够连续的 space(ArrayBuffer 必须 在浏览器进程的虚拟地址 space 中是连续的,否则你会产生巨大的性能影响)。您会尝试分配 256MiB,有时会遇到硬失败。如果浏览器不是多进程的,这将变得非常困难,因为所有其他选项卡都在争夺 32 位虚拟地址 space。浏览器 were a bit silly a few years ago, they got better,但 32 位并不多。

WebAssembly 由 WebAssembly.Memory 支持,它是 ArrayBuffer 的一种特殊类型。这意味着 WebAssembly 实现可以很聪明 ArrayBuffer。在 32 位上没有什么可做的:如果你 运行 超出连续地址 space 那么 VM 就不能做太多。但是在 64 位平台上有很多地址 space。浏览器实现可以选择阻止您创建太多 WebAssembly.Memory 个实例(分配虚拟内存 几乎 是免费的,但不是完全免费),但您应该能够获得一些4GiB 分配。请注意,浏览器只会虚拟地分配 space,并为您所说的最少页面数提交物理地址。之后它只会在您使用 grow_memory 时进行物理分配。这可能会失败(物理内存与 RAM 的数量一样多,给予或接受交换 space),但它 更可预测。

一个实现可以在 32 位平台上使用类似的技巧(过度提交但保持 PROT_NONE 并且没有物理分配),假设碎片允许,但这取决于实现以及它认为这会如何影响自动单反。实际上,当周围没有太多东西时,很难找到记忆,但实际上和物理上都是如此。

WebAssembly 当前被指定为 ILP32 进程:指针为 32 位。因此,您被硬性限制为 4GiB。我们以后可能会添加wasm64

我对上面的答案、评论和谷歌搜索做了一些总结;有两个问题阻止将 WebAssembly 用于需要大量内存的使用项目:

  • 当前的 WebAssembly 实现遵循 32 位寻址 space 模型,因此在 wasm64 出来之前,没有希望使用超过 4gb 的内存 (proposal overview) .
  • 浏览器任意决定分配给页面的内存量。这(主要)是出于安全原因,因为人们喜欢将网页视为比桌面应用程序更“安全”的东西。

希望这两个问题都能得到解决。我希望浏览器能够以明确的方式公开这些限制;就像当页面请求使用您的相机时收到通知一样,您应该简单地通知用户页面需要大量内存并阻止它直到您回答。

相关提案(see their current stages here):

多个记忆

This proposal adds the ability to use multiple memories within a single Wasm module. In the current version of Wasm, an application can already create multiple memories, but only by splitting things up into multiple modules. A single module or function cannot refer to multiple memories at the same time. Consequently, it is not possible to e.g. efficiently transfer data from one memory to another, since that necessarily involves an individual function call into a different module per value.

https://github.com/WebAssembly/multi-memory/blob/master/proposals/multi-memory/Overview.md

内存64

This page describes a proposal to support linear memory of sizes larger than 2^32 bits. It provides no new instructions, but instead extends the currently existing instructions to allow 64-bit indexes.

WebAssembly linear memory objects have sizes measured in pages. Each page is 65536 (2^16) bytes. In WebAssembly version 1, a linear memory can have at most 65536 pages, for a total of 2^32 bytes (4 gibibytes). In addition to this page limit, all memory instructions currently use the i32 type as a memory index. This means they can address at most 2^32 bytes as well.

https://github.com/WebAssembly/memory64/blob/master/proposals/memory64/Overview.md