在模块实例之间共享 WebAssembly.Memory
Share WebAssembly.Memory between module instances
我想使用之前 Module 实例创建的 WebAssembly.Memory 对象实例化一个 WebAssembly 模块(所有这些都使用 emscripten 的胶水代码),这可行吗?
自己创建一个内存对象然后在一个或多个 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
(参见documentation and settings.js,这意味着将-s Modularize=1 -s EXPORT_NAME='MY_MODULE_NAME_1'
添加到emcc
command-line。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-like WASM 实例,您现在可以与两个模块交互:
createInstance1.then( (instance1) => {
createInstance2.then( (instance2) => {
useWasm(instance1, instance2);
});
});
但是 - 这里有一个严重的警告:如果两个模块都试图在同一内存中分配动态内存,它们将覆盖 each-other 分配的缓冲区!到目前为止我还没有找到解决这个问题的方法:-(.
请参阅 This repo 中的工作示例。
我想使用之前 Module 实例创建的 WebAssembly.Memory 对象实例化一个 WebAssembly 模块(所有这些都使用 emscripten 的胶水代码),这可行吗?
自己创建一个内存对象然后在一个或多个 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
(参见documentation and settings.js,这意味着将-s Modularize=1 -s EXPORT_NAME='MY_MODULE_NAME_1'
添加到emcc
command-line。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-like WASM 实例,您现在可以与两个模块交互:
createInstance1.then( (instance1) => {
createInstance2.then( (instance2) => {
useWasm(instance1, instance2);
});
});
但是 - 这里有一个严重的警告:如果两个模块都试图在同一内存中分配动态内存,它们将覆盖 each-other 分配的缓冲区!到目前为止我还没有找到解决这个问题的方法:-(.
请参阅 This repo 中的工作示例。