传输 TypedArray 和缓冲区时的注意事项
【Considerations when transferring TypedArrays and Buffers】
所有 <TypedArray> | <Buffer> 实例都是底层 <ArrayBuffer> 的视图。也就是说,实际上是 ArrayBuffer 存储原始数据,而 TypedArray 和 Buffer 对象提供查看和操作数据的方式。通常也可以在同一个 ArrayBuffer 实例上创建多个视图。使用转移列表来转移 ArrayBuffer 时必须非常小心,因为这样会导致所有共享该 ArrayBuffer 的 TypedArray 和 Buffer 实例变得无法使用。
【All <TypedArray> | <Buffer> instances are views over an underlying
<ArrayBuffer>. That is, it is the ArrayBuffer that actually stores
the raw data while the TypedArray and Buffer objects provide a
way of viewing and manipulating the data. It is possible and common
for multiple views to be created over the same ArrayBuffer instance.
Great care must be taken when using a transfer list to transfer an
ArrayBuffer as doing so causes all TypedArray and Buffer
instances that share that same ArrayBuffer to become unusable.】
const ab = new ArrayBuffer(10);
const u1 = new Uint8Array(ab);
const u2 = new Uint16Array(ab);
console.log(u2.length); // prints 5
port.postMessage(u1, [u1.buffer]);
console.log(u2.length); // prints 0 对于 Buffer 实例来说,底层的 ArrayBuffer 是否可以被传输或克隆完全取决于实例的创建方式,而这一点通常无法可靠地确定。
【For Buffer instances, specifically, whether the underlying
ArrayBuffer can be transferred or cloned depends entirely on how
instances were created, which often cannot be reliably determined.】
ArrayBuffer 可以使用 markAsUntransferable() 标记,表示它应该始终被克隆,而绝不被传输。
【An ArrayBuffer can be marked with markAsUntransferable() to indicate
that it should always be cloned and never transferred.】
根据 Buffer 实例的创建方式,它可能拥有或不拥有其底层的 ArrayBuffer。除非确定 Buffer 实例拥有该 ArrayBuffer,否则不能转移它。特别是,对于从内部 Buffer 池创建的 Buffer(例如使用 Buffer.from() 或 Buffer.allocUnsafe()),无法转移它们,并且它们总是被克隆,这会发送整个 Buffer 池的副本。这种行为可能导致意外的更高内存使用和潜在的安全问题。
【Depending on how a Buffer instance was created, it may or may
not own its underlying ArrayBuffer. An ArrayBuffer must not
be transferred unless it is known that the Buffer instance
owns it. In particular, for Buffers created from the internal
Buffer pool (using, for instance Buffer.from() or Buffer.allocUnsafe()),
transferring them is not possible and they are always cloned,
which sends a copy of the entire Buffer pool.
This behavior may come with unintended higher memory
usage and possible security concerns.】
有关 Buffer 池的更多详情,请参见 Buffer.allocUnsafe()。
【See Buffer.allocUnsafe() for more details on Buffer pooling.】
使用 Buffer.alloc() 或 Buffer.allocUnsafeSlow() 创建的 Buffer 实例的 ArrayBuffer 总是可以被传输,但这样做会使这些 ArrayBuffer 的所有其他现有视图不可用。
【The ArrayBuffers for Buffer instances created using
Buffer.alloc() or Buffer.allocUnsafeSlow() can always be
transferred but doing so renders all other existing views of
those ArrayBuffers unusable.】