传输 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.from()
或 Buffer.allocUnsafe()
)创建的 Buffer
,传输它们是不可能的,它们总是被克隆,这会发送整个 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 Buffer
s 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 ArrayBuffer
s for Buffer
instances created using
Buffer.alloc()
or Buffer.allocUnsafeSlow()
can always be
transferred but doing so renders all other existing views of
those ArrayBuffer
s unusable.