【问题标题】:Performant read uint12 binary from file in JavaScript高性能从 JavaScript 文件中读取 uint12 二进制文件
【发布时间】:2021-04-11 17:00:08
【问题描述】:

我需要将二进制 blob 从文件读取到 JavaScript 数组中。 blob 是 little endian,uint 12 位,即

---------------------------------
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-------------------------------|
|         data1[7:0]            |
|-------------------------------|
| data2[3:0]    | data1[11:8]   |
|-------------------------------|
|           data2[11:4]         |
---------------------------------

似乎TypedArraysbit shifting 可能是最好的方法(这就是我在 Python 中解决的方法),但我正在努力让它变得非常高效(10 MB 的亚秒级时间尺度)

我只是在使用浏览器工具测试应用性能

【问题讨论】:

  • edit您的问题显示您尝试了哪些代码以及您如何测试性能。

标签: javascript performance binary


【解决方案1】:

哇,我花了一些时间才弄清楚这个...最终不得不使用 Webassembly,这是其他人的代码,以防其他人想要这样做:

parse12bit.c

#include <stdint.h>

__attribute__((used)) void parse12bit(unsigned char *buffer, int num_bytes, uint16_t *data)
{
  int i = 0, j = 0;
  do
  {
    data[j] = buffer[i] + ((buffer[i + 1] & 0xF) << 8);
    data[j + 1] = ((buffer[i + 1] & 0xF0) >> 4) + (buffer[i + 2] << 4);
    i = i + 3;
    j = j + 2;
  } while (i < num_bytes);
}

build.sh(使用brew install emscripten在mac上安装emcc)

emcc ./parse12bit.c \
  --target=wasm32-unknown-unknown-wasm \
  --optimize=3 \
  -nostdlib \
  -Wl,--export-all \
  -Wl,--no-entry \
  -Wl,--allow-undefined \
  -s ALLOW_MEMORY_GROWTH=1 \
  -o parse12bit.wasm

parseData.js

import fs from 'fs';
import path from 'path';

interface Parse12bit extends Function {
  // passing location of pointer (first element of array), respects C convention
  (buffer: number, length: number, data: number): void;
}

export const parseDataC = async (bufferArray: Uint8Array) => {
  // Load the wasm into a buffer.
  const wasmBuf = fs.readFileSync(
    path.join(__dirname, `/wasm/parse12bit.wasm`)
  );

  // Make an instance.
  const res = await WebAssembly.instantiate(wasmBuf, {});

  // Get function.
  const parse12bit = res.instance.exports.parse12bit as Parse12bit;
  const memory = res.instance.exports.memory as WebAssembly.Memory;

  // calculate total size of shared memory
  const totalBytes =
    bufferArray.length * Uint8Array.BYTES_PER_ELEMENT +
    1 * Int32Array.BYTES_PER_ELEMENT +
    (bufferArray.length * Uint16Array.BYTES_PER_ELEMENT * 8) / 12;

  // grow memory if necessary, default created memory not large enough in original implementaiton
  // memory is grown in 64 KiB chunks
  if (memory.buffer.byteLength < totalBytes) {
    memory.grow(Math.ceil((totalBytes - memory.buffer.byteLength) / 65536));
  }

  // Create the input arrays.
  let offset = 0;
  const buffer = new Uint8Array(memory.buffer, offset, bufferArray.length);
  buffer.set(Uint8Array.from(bufferArray));

  offset += buffer.length * Uint8Array.BYTES_PER_ELEMENT;
  const numBytes = new Int32Array(memory.buffer, offset, 1);
  numBytes.set([bufferArray.length]);

  offset += Int32Array.BYTES_PER_ELEMENT;
  const data = new Uint16Array(
    memory.buffer,
    offset,
    (bufferArray.length * 8) / 12
  ); // data in 12 bit at end

  // Call the function.
  parse12bit(buffer.byteOffset, numBytes.byteOffset, data.byteOffset);

  // // Show the results.
  console.log(data);
};

注意,决赛来自this very helpful blog post

【讨论】:

    猜你喜欢
    • 2011-03-31
    • 2017-03-28
    • 2013-07-24
    • 2018-11-19
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2023-03-13
    • 2018-08-24
    相关资源
    最近更新 更多