我有一个非常简单的打字稿代码来解析特定的数据格式,输入是uint8array。我已经尽可能地对其进行了优化,但是我认为,这个相当简单的解析器应该能够比以JS运行更快地运行速度。我想尝试使用AssemblyScript在Web组件中编写它,以确保我不会遇到JavaScript引擎的任何怪癖。
正如我现在想出的那样,我不能只将打字机传递给WASM并自动工作。据我了解,我可以将指针传递到数组,并且应该能够直接从WASM访问它而无需复制数组。但是我无法与汇编一起使用。
以下是一个最小示例,它显示了我如何将ArrayBuffer传递给WASM。
设置WASM导出的代码主要来自自动生成的样板:
const fs = require("fs");
const compiled = new WebAssembly.Module(
fs.readFileSync(__dirname + "/build/optimized.wasm")
);
const imports = {
env: {
abort(msgPtr, filePtr, line, column) {
throw new Error(`index.ts: abort at [${line}:${column}]`);
}
}
};
Object.defineProperty(module, "exports", {
get: () => new WebAssembly.Instance(compiled, imports).exports
});
以下代码调用wasm,index.js是上面的胶代码。
const m = require("./index.js");
const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
const result = m.parse(data.buffer);
和汇编为WASM的汇编为:
import "allocator/arena";
export function parse(offset: usize): number {
return load<u8>(offset);
}
我执行该代码时会获得" runtimeerror:内存访问"。
主要问题是,我从WASM回来的错误根本无济于事。显然,我错过了它在幕后实际工作的一些主要方面。
我如何使用"汇编"实际上如何将打字机或阵列扣从JS传递给WASM?
在汇编中,有很多方法可以从内存中读取数据。获取此数据的最快,最快的方法是在您的模块功能导入中使用链接函数以返回指针到数据本身。
let myData = new Float64Array(100); // have some data in AssemblyScript
// We should specify the location of our linked function
@external("env", "sendFloat64Array")
declare function sendFloat64Array(pointer: usize, length: i32): void;
/**
* The underlying array buffer has a special property called `data` which
* points to the start of the memory.
*/
sendFloat64Data(myData.buffer.data, myData.length);
然后在JavaScript中,我们可以在链接函数中使用Float64Array
构造函数直接返回值。
/**
* This is the fastest way to receive the data. Add a linked function like this.
*/
imports.env.sendFloat64Array = function sendFloat64Array(pointer, length) {
var data = new Float64Array(wasmmodule.memory.buffer, pointer, length);
};
但是,有一种获取数据的清晰方法,它涉及从汇编返回参考,然后使用indayblyscript加载程序。
let myData = new Float64Array(100); // have some data in AssemblyScript
export function getData(): Float64Array {
return myData;
}
然后在JavaScript中,我们可以使用汇编提供的asutil加载器。
import { instantiateStreaming } from "assemblyscript/lib/loader";
let wasm: ASUtil = await instantiateStreaming(fetch("myAssemblyScriptModule.wasm"), imports);
let dataReference: number = wasm.getData();
let data: Float64Array = wasm.getArray(Float64Array, dataReference);
我强烈建议出于代码清晰度使用第二个示例,除非性能绝对至关重要。
祝您汇编项目好运!