ES2024系列 - 可调节大小的ArrayBuffer

239 阅读3分钟

进入到Stage4阶段

2023年9月份,可调节大小的ArrayBuffer这一提议进入到了Stage4阶段。各大执行环境也已经实现了该特性。

具体的API

具体的API涉及到ArrayBufferSharedArrayBuffer两个类型,列出清单如下:

ArrayBuffer

变化类型API描述
修改构造函数constructor(byteLength [, {maxByteLength}])
新增了maxByteLength可选项,代表该ArrayBuffer允许的最大字节数,该参数表示该ArrayBuffer可以调节大小
新增方法ArrayBuffer
.prototype.resize(newByteLength)
调节ArrayBuffer的大小,
resize(0)也是可以的
修改方法ArrayBuffer.prototype.slice(start, end)
返回一个新的不可调节大小的ArrayBuffer
新增GetterArrayBuffer.prototype.resizable
是否可以调节大小
新增GetterArrayBuffer.prototype.maxByteLength
允许的最大字节数

SharedArrayBuffer

变化类型API描述
修改构造函数constructor(byteLength [, {maxByteLength}])
新增了maxByteLength可选项,代表允许的最大字节数,传入该参数表示可调节大小
新增方法SharedArrayBuffer
.prototype.grow(newByteLength)
调节SharedArrayBuffer的字节大小。要注意的是,只能调大不能调小,如果比byteLength小,该方法将会抛异常
修改方法SharedArrayBuffer
.prototype.slice(start, end)
返回一个新的不可调节大小的SharedArrayBuffer
新增GetterSharedArrayBuffer
.prototype.growable
是否可以调节大小,新建实例时有maxByteLength 则代表可调节大小
新增GetterSharedArrayBuffer
.prototype.maxByteLength
允许的最大字节数

ArrayBuffer是什么

ArrayBuffer的实例对象代表着一段通用的二进制数据缓冲区。通过该对象,Javascript可以以字节为单位直接存储和操作二进制数据。可以用来处理如图像、音频等数据。

所解决的问题

以前,我们创建一个ArrayBuffer时,会指定大小,一旦创建之后是没有办法修改其大小的:

const buffer = new ArrayBuffer(8);
// 字节长度是8,无法修改
console.log(buffer.byteLength);

如果我们确实需要改变其大小,我们只能重新创建一个新的ArrayBuffer对象。这会带来不小的性能损耗,代码也会变得复杂。

提议者举了两个具体的例子:WebAssemblyWebGPU

WebAssembly

该新特性的提议者在提案中用WebAssembly举了个例子: 当WebAssembly的内存增长时,由于ArrayBuffer的大小不可以改变,所以它只能提供一个新的ArrayBuffer的实例,原有实例会变得不可用。这时Javascript不得不通过回调函数等形式同步的去更新其TypedArray,提议者用代码举例如下:

// wasm的内存一旦增长,其原有的ArrayBuffer就变得不可用了
let U8 = new Uint8Array(WebAssembly.Memory.buffer);

function derefPointerIntoWasmMemory(idx) {
  // Uint8Array的长度如果是0,则说明wasm的内存已经增长了,从而导致了Uint8Array所依赖的ArrayBuffer已经不可用了,从而导致Uint8Array不可用。
  if (U8.length === 0) {
   // 这时需要重建Uint8Array,WebAssembly.Memory.buffer原先指向的内容已经不可用
    U8 = new Uint8Array(WebAssembly.Memory.buffer);
  }
  doSomethingWith(U8[idx]);
}

WebGPU

WebGPU社区也希望缓冲区内存变化时,ArrayBuffer能够重复使用,而不是每次都重新新建ArrayBuffer实例,在动画期间,每次重新新建ArrayBuffer实例会增加垃圾回收的压力,从而导致卡顿。

原始提议文档

提议者还阐述了下面几项内容:

  1. 可调节大小的功能对TypedArray的影响。
  2. 具体的实现方法。
  3. 安全问题。
  4. 为什么不直接将ArrayBuffer改成可调节的,而是要加个参数?
  5. 为什么要限制最大字节数?
  6. 为什么SharedArrayBuffer不可以调小?
  7. SharedArrayBuffer的调大字节长度功能是如何与内存模型配合工作的?

如果想了解更多,可参考原始提议文档

此篇结束。