【问题标题】:Share WebAssembly.Memory between module instances在模块实例之间共享 WebAssembly.Memory
【发布时间】:2019-09-19 03:57:35
【问题描述】:

我想使用由前一个 Module 实例创建的 WebAssembly.Memory 对象来实例化一个 WebAssembly 模块(所有这些都使用 emscripten 的胶水代码),这可行吗?

【问题讨论】:

    标签: emscripten webassembly


    【解决方案1】:

    自己创建一个内存对象,然后在一个或多个 WASM 模块的实例化过程中注入它会更容易一些。我通过覆盖 instantiateWasm 设法使用 Emscripten 做到了这一点。

    首先创建一个将由 WASM 实例共享的内存:

    var TOTAL_MEMORY = 16777216;
    var WASM_PAGE_SIZE = 65536;
    var wasmMemory = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE });
    var buffer = wasmMemory.buffer;
    

    然后实现一个自定义实例化器,将这个内存注入到导入对象中:

    function wasmInstantiator(wasmBinary) {
      return (info, receiveInstance) => {
        var importObject = Object.assign({}, info);
        importObject['env']['memory'] = wasmMemory;
        WebAssembly.instantiateStreaming(fetch(wasmBinary, { credentials: 'same-origin' }), importObject)
        .then((output) => { receiveInstance(output['instance']); },
              (err) => { console.error('wasm streaming compile failed: ' + err);});
         return {};
      };
    };
    

    现在您可以使用相同的内存来实例化这两个模块。这里我推荐使用Modularize(参见documentationsettings.js,这意味着将-s Modularize=1 -s EXPORT_NAME='MY_MODULE_NAME_1'添加到emcc命令行。Emscripten将创建一个名为MY_MODULE_NAME_1的函数,它接受一个Module对象可以覆盖某些元素,例如实例化器和内存。

    var createInstance1 = MY_MODULE_NAME_1( { instantiateWasm: wasmInstantiator('module1.wasm') , TOTAL_MEMORY, buffer } );
    var createInstance2 = MY_MODULE_NAME_2( { instantiateWasm: wasmInstantiator('module2.wasm') , TOTAL_MEMORY, buffer } );
    

    使用这些类似于 Promise 的 WASM 实例,您现在可以与这两个模块进行交互:

    createInstance1.then( (instance1) => {
       createInstance2.then( (instance2) => {
           useWasm(instance1, instance2);
       });
    });
    

    但是 - 这里有一个严重的警告:如果两个模块都试图在同一内存中分配动态内存,它们会覆盖彼此分配的缓冲区!到目前为止,我还没有找到解决这个问题的方法:-(。

    请参阅This repo 中的工作示例。

    【讨论】:

    • 哇,谢谢(我也尝试将第一个实例的内存对象注入到第二个实例中,但没有奏效..)。关于动态分配问题,不能只禁用内存增长吗?
    • 禁用内存增长仅意味着 ArrayBuffer 不会增长,但使用 _malloc 的动态分配在大多数情况下不会增长内存 - 只会在其中找到未使用的区域。因此,即使我们不增加内存,malloc 仍然可用。我不确定从 emscripten wasm 文件中删除“malloc”支持的简单方法是什么……但我担心没有动态分配的程序非常有限——标准库中的基本集合和字符串经常使用动态分配。没有它们,C/C++ 将受到严重限制。
    • 好的,我明白了:/ 那么我猜最好将我的项目链接到一个 wasm 模块中。无论如何,谢谢你的帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    相关资源
    最近更新 更多