【问题标题】:Memory limits in webassemblyWebAssembly 中的内存限制
【发布时间】:2017-03-17 23:57:35
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: memory browser webassembly


    【解决方案1】:

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

    对于 asm.js,很难知道 ArrayBuffer 将如何使用,并且在某些 32 位平台上,您经常会遇到进程碎片,这使得很难在进程的虚拟空间中分配足够的连续空间内存(ArrayBuffer 必须在浏览器进程的虚拟地址空间中是连续的,否则你会受到巨大的性能影响)。您会尝试分配 256MiB,有时会出现硬故障。如果浏览器不是多进程的,这将变得非常困难,因为所有其他选项卡都在竞争 32 位的虚拟地址空间。浏览器 were a bit silly a few years ago, they got better,但 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

    【讨论】:

    • 其实我觉得WebAssembly.Memory API 跟这个没什么关系。事实上,Wasm 模块可以定义自己的内存,不像 asm.js,它总是从 JS 导入,所以引擎无法区分用例。
    • 也就是说,JS引擎的内存限制大多不是硬件或地址空间的限制,而是为了防止网页用OOM杀死机器,这在某些操作系统上很容易。这也适用于 Wasm。我不确定我们是否已经解决了这方面的问题。
    【解决方案2】:

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

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

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

    【讨论】:

    • 是什么让你认为你不能用 32 位编写严肃的软件?如今,大多数桌面软件仍以 32 位运行,更不用说移动设备了。
    • 对于“严重”,我的意思是“需要大量内存”。抱歉不够清楚。
    【解决方案3】:

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

    多重记忆

    该提议增加了在单个 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      • 2017-12-10
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多