20

WebAssembly 程序的内存分配限制策略是什么?

当前的(硬)javascript引擎内存限制会被继承吗?例如,是否可以编写需要数百兆内存的实际应用程序?

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

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

4

3 回答 3

15

WebAssembly 有一个WebAssembly.Memory对象,而二进制文件有一个内存部分。通过这些,开发人员提供了关于最小和最大内存使用的有根据的猜测,然后 VM 至少分配最小值(或失败)。然后,开发人员可以在运行时询问更多grow_memory像 Emscripten 这样的工具将在幕后使用malloc(它有点类似于sbrk)。

对于 asm.js,很难知道ArrayBuffer将如何使用它,并且在某些 32 位平台上,您经常会遇到进程碎片,这使得很难在进程的虚拟内存中分配足够的连续空间(ArrayBuffer 必须是连续的)在浏览器进程的虚拟地址空间中,否则你会有一个巨大的性能命中)。您会尝试分配 256MiB,有时会出现硬故障。如果浏览器不是多进程的,这将变得非常困难,因为所有其他选项卡都在竞争 32 位虚拟地址空间。几年前浏览器有点傻,它们变得更好了,但是 32 位并没有什么好转的。

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

假设允许碎片,实现可以在 32 位平台上使用类似的技巧(过度提交但保持PROT_NONE而不是物理分配),但这取决于实现以及它认为这如何影响 ASLR。实际上,当没有太多可去的地方,但实际上和物理上,很难找到记忆。

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

于 2016-11-04T14:31:52.853 回答
7

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

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

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

于 2016-11-06T20:07:40.103 回答
2

相关提案(在此处查看其当前阶段):

多重记忆

该提议增加了在单个 Wasm 模块中使用多个内存的能力。在当前版本的 Wasm 中,应用程序已经可以创建多个内存,但只能通过将内容拆分为多个模块来实现。单个模块或函数不能同时引用多个内存。因此,不可能例如有效地将数据从一个存储器传输到另一个存储器,因为这必然涉及对每个值的不同模块的单独函数调用。

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

内存64

本页描述了支持大于 2^32 位的线性内存的建议。它没有提供新的指令,而是扩展了当前存在的指令以允许 64 位索引。

WebAssembly 线性内存对象的大小以页面为单位。每页为 65536 (2^16) 字节。在 WebAssembly 版本 1 中,线性内存最多可以有 65536 个页面,总共 2^32 字节(4 GB)。除了这个页限制之外,目前所有的内存指令都使用 i32 类型作为内存索引。这意味着它们最多也可以寻址 2^32 个字节。

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

于 2020-09-17T07:41:49.617 回答