You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Javascript中用Int8、Int16存储大型数据结构优化性能

实现方案

核心思路

你需要的三个字段总长度刚好为32位(8bit id + 8bit harm + 16bit val),可以直接打包进单个Uint32类型的存储单元,使用连续内存的Uint32Array存储所有数据,相比普通JS对象的哈希表存储,随机访问和批量遍历的性能都会有明显提升,和你之前优化Float32音频数组的效果一致。

位布局定义

我们统一约定32位空间的位分配规则(你也可以根据自己的使用习惯调整偏移量):

  • 最高8位(位2431):存储固定的`id`值,取值范围0127,完全覆盖Int8需求
  • 中间8位(位1623):存储固定的`harm`值,取值范围0127,完全覆盖Int8需求
  • 最低16位(位015):存储可变的`val`值,取值范围02047,远小于Int16的最大值32767,完全够用

具体实现步骤

1. 预定义常量与存储结构

// 位掩码与偏移量常量,避免魔法数
const ID_OFFSET = 24;
const HARM_OFFSET = 16;
const VAL_MASK = 0xFFFF;
const META_MASK = 0xFFFF0000;

// id和harm取值都是0~127,所有可能的组合总数为128*128=16384,仅占用64KB内存,空间完全足够
const DATA_TOTAL_COUNT = 128 * 128;
const dataBuffer = new Uint32Array(DATA_TOTAL_COUNT);

2. 构建属性名元信息映射

因为你原有代码是通过属性名(比如EvenHarmonics)访问数据,所以需要先把所有属性对应的固定id、harm值预存在映射表里:

const KeyMeta = {
  MIDISource: {id: 0, harm: 0},
  MIDIChannel: {id: 1, harm: 1},
  MIDISplit: {id: 2, harm: 1},
  MultiTouch: {id: 3, harm: 1},
  // 把剩下的5000个属性的元信息全部按上面的格式补全
};

3. 初始化填充数据

把原有Data对象的所有数据打包写入dataBuffer:

Object.entries(KeyMeta).forEach(([key, {id, harm}]) => {
  const originalVal = Data[key].val;
  const index = id * 128 + harm;
  // 按位规则打包成32位整数写入数组
  dataBuffer[index] = (id << ID_OFFSET) | (harm << HARM_OFFSET) | (originalVal & VAL_MASK);
});

4. 兼容原有访问方式(可选)

如果你不想修改原有代码的访问语法,可以用Proxy封装一层,完全兼容你原来的访问写法:

const Data = new Proxy({}, {
  get(target, prop) {
    const meta = KeyMeta[prop];
    if (!meta) return undefined;
    const index = meta.id * 128 + meta.harm;
    const packed = dataBuffer[index];
    return {
      id: (packed >> ID_OFFSET) & 0xFF,
      harm: (packed >> HARM_OFFSET) & 0xFF,
      get val() {
        return dataBuffer[index] & VAL_MASK;
      },
      set val(newVal) {
        // 仅修改val对应的低16位,保留固定的id、harm位
        dataBuffer[index] = (dataBuffer[index] & META_MASK) | (newVal & VAL_MASK);
      }
    }
  }
});

封装完成后,你原有代码的Data.EvenHarmonics.val读取和赋值操作都可以直接正常运行,不需要做任何修改。

极端性能优化场景

如果你的使用场景对性能要求极高,可以跳过Proxy封装,直接通过下标访问数据,避免Proxy的代理开销:

// 读取val
const getVal = (id, harm) => dataBuffer[id * 128 + harm] & VAL_MASK;
// 写入val
const setVal = (id, harm, newVal) => {
  const idx = id * 128 + harm;
  dataBuffer[idx] = (dataBuffer[idx] & META_MASK) | (newVal & VAL_MASK);
};

内容的提问来源于stack exchange,提问作者Mike Bryant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:06:02