【发布时间】:2019-02-02 06:11:55
【问题描述】:
我正在通过 wasm-bindgen 在 Rust 中构建一个 WebAssembly 模块以用于 Cloudflare Workers。该模块总体上非常基础;它有一个名为 process 的函数,它将两个二进制文件(由两个 Uint8BitArray 表示)和一个 json_value(由 serde 解释)作为输入,并产生 None 或字符串,通常是这样的。
#[wasm_bindgen]
pub fn process(
binary_a: &[u8],
binary_b: &[u8],
json_value: &JsValue,
) -> Option<String> {
Some(String::new())
}
实例化 WebAssembly 模块的胶水代码与 wasm-bindgen --no-modules 命令几乎相同,我只是将第 93 行的初始化条件更改为 true:
self = {};
(function() {
var wasm;
const __exports = {};
let cachegetUint8Memory = null;
function getUint8Memory() {
if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== wasm.memory.buffer) {
cachegetUint8Memory = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory;
}
let WASM_VECTOR_LEN = 0;
function passArray8ToWasm(arg) {
const ptr = wasm.__wbindgen_malloc(arg.length * 1);
getUint8Memory().set(arg, ptr / 1);
WASM_VECTOR_LEN = arg.length;
return ptr;
}
const heap = new Array(32);
heap.fill(undefined);
heap.push(undefined, null, true, false);
let stack_pointer = 32;
function addBorrowedObject(obj) {
if (stack_pointer == 1) throw new Error('out of js stack');
heap[--stack_pointer] = obj;
return stack_pointer;
}
let cachedTextDecoder = new TextDecoder('utf-8');
function getStringFromWasm(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));
}
let cachedGlobalArgumentPtr = null;
function globalArgumentPtr() {
if (cachedGlobalArgumentPtr === null) {
cachedGlobalArgumentPtr = wasm.__wbindgen_global_argument_ptr();
}
return cachedGlobalArgumentPtr;
}
let cachegetUint32Memory = null;
function getUint32Memory() {
if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== wasm.memory.buffer) {
cachegetUint32Memory = new Uint32Array(wasm.memory.buffer);
}
return cachegetUint32Memory;
}
/**
* @param {Uint8Array} arg0
* @param {Uint8Array} arg1
* @param {any} arg2
* @returns {string}
*/
__exports.process = function(arg0, arg1, arg2) {
const ptr0 = passArray8ToWasm(arg0);
const len0 = WASM_VECTOR_LEN;
const ptr1 = passArray8ToWasm(arg1);
const len1 = WASM_VECTOR_LEN;
const retptr = globalArgumentPtr();
try {
wasm.process(retptr, ptr0, len0, ptr1, len1, addBorrowedObject(arg2));
const mem = getUint32Memory();
const rustptr = mem[retptr / 4];
const rustlen = mem[retptr / 4 + 1];
if (rustptr === 0) return;
const realRet = getStringFromWasm(rustptr, rustlen).slice();
wasm.__wbindgen_free(rustptr, rustlen * 1);
return realRet;
} finally {
wasm.__wbindgen_free(ptr0, len0 * 1);
wasm.__wbindgen_free(ptr1, len1 * 1);
heap[stack_pointer++] = undefined;
}
};
function init(path_or_module) {
let instantiation;
const imports = { './phototaxon_worker_utils': __exports };
if (true) {
instantiation = WebAssembly.instantiate(path_or_module, imports)
.then(instance => {
return { instance, module: path_or_module }
});
} else {
const data = fetch(path_or_module);
if (typeof WebAssembly.instantiateStreaming === 'function') {
instantiation = WebAssembly.instantiateStreaming(data, imports);
} else {
instantiation = data
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.instantiate(buffer, imports));
}
}
return instantiation.then(({instance}) => {
wasm = init.wasm = instance.exports;
});
};
self.wasm_bindgen = Object.assign(init, __exports);
})();
self.wasm_bindgen(MODULE).then(() => { XXX }).catch(error => console.log(error));
我使用cloudworker 试用了整个脚本,它运行起来没有问题。然后,我用Preview Service API 尝试了相同的脚本,它在几次尝试中确实运行良好,直到它开始抛出错误:
RangeError: WebAssembly Instantiation: Out of memory: wasm memory
at init (worker.js:1200:35)
at Module.<anonymous> (worker.js:1878:15)
at __webpack_require__ (worker.js:20:30)
at worker.js:84:18
at worker.js:87:10
这发生在实例化时,不管发送的请求是什么(初始化后发生的不是。
我一直在尝试精简我的 Webassembly 脚本,但即使是 hello-world 类型的函数也被拒绝了。不知道怎么调试,是不是和glue-code、rust code或者Cloudflare的Preview Service有关?
【问题讨论】:
-
您使用的是默认分配器吗? IIRC,您可以使用
wee_alloc显着减小二进制大小。
标签: rust cloudflare-workers wasm-bindgen