Как я могу передать ArrayBuffer из JS в AssemblyScript / Wasm? - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть довольно простой фрагмент кода Typescript, который анализирует определенный формат данных, входные данные представляют собой массив UInt8Array.Я оптимизировал его настолько, насколько смог, но я думаю, что этот довольно простой парсер должен быть в состоянии работать быстрее, чем я могу заставить его работать как JS.Я хотел попробовать написать его в веб-сборке с использованием AssemblyScript, чтобы убедиться, что я не сталкиваюсь с какими-либо изюминками движков Javascript.

Как я понял, я не могу просто передать TypedArray в Wasm и заставить его работать автоматически.Насколько я понимаю, я могу передать указатель на массив и должен иметь возможность доступа к нему напрямую из Wasm без копирования массива.Но я не могу заставить это работать с AssemblyScript.

Ниже приведен минимальный пример, показывающий, как я не могу передать 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 просто не полезно, чтобы понять это самостоятельно.Я, очевидно, упускаю некоторые основные аспекты того, как это на самом деле работает за кулисами.

Как на самом деле передать TypedArray или ArrayBuffer из JS в Wasm с использованием AssemblyScript?

1 Ответ

0 голосов
/ 18 февраля 2019

В AssemblyScript есть много способов чтения данных из памяти.Самый быстрый и быстрый способ получить эти данные - использовать связанную функцию в импорте функции вашего модуля, чтобы вернуть указатель на сами данные.

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);
};

Однако есть гораздо более простой способ получения данных, и он включает в себя возврат ссылки из AssemblyScript, а затем использование загрузчика AssemblyScript.

let myData = new Float64Array(100); // have some data in AssemblyScript

export function getData(): Float64Array {
  return myData;
}

Тогда в JavaScript мы можем использовать загрузчик ASUtil, предоставляемый AssemblyScript.

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);

Я настоятельно рекомендую использовать второй пример для ясности кода, если производительность не является абсолютно критической.

Удачи в вашем проекте AssemblyScript!

...