diff options
author | James M Snell <jasnell@gmail.com> | 2020-05-05 17:57:40 +0300 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2020-05-08 01:59:15 +0300 |
commit | baba42c38bbda5225e09147fe4a869fa4a4a1110 (patch) | |
tree | 342dabe91516b375dbc93a65338504c211ed9d1a /doc/api/worker_threads.md | |
parent | e454e9b33f2a3e21d0c36a96d47cf39ce3e42d6c (diff) |
doc: add warnings about transferring Buffers and ArrayBuffer
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/33252
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Mathias Buus <mathiasbuus@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'doc/api/worker_threads.md')
-rw-r--r-- | doc/api/worker_threads.md | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index b3f4aca313b..70f1273f3ab 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -396,6 +396,51 @@ posting without having side effects. For more information on the serialization and deserialization mechanisms behind this API, see the [serialization API of the `v8` module][v8.serdes]. +#### Considerations when transferring TypedArrays and Buffers + +All `TypedArray` and `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 will cause all `TypedArray` and `Buffer` +instances that share that same `ArrayBuffer` to become unusable. + +```js +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 +``` + +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. + +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.alloc()`), +transferring them is not possible and they will always be cloned, +which sends a copy of the entire `Buffer` pool. +This behavior may come with unintended higher memory +usage and possible security concerns. + +See [`Buffer.allocUnsafe()`][] for more details on `Buffer` pooling. + +The `ArrayBuffer`s for `Buffer` instances created using +`Buffer.alloc()` or `Buffer.allocUnsafeSlow()` can always be +transferred but doing so will render all other existing views of +those `ArrayBuffer`s unusable. + ### `port.ref()` <!-- YAML added: v10.5.0 @@ -767,6 +812,7 @@ active handle in the event system. If the worker is already `unref()`ed calling [`'exit'` event]: #worker_threads_event_exit [`AsyncResource`]: async_hooks.html#async_hooks_class_asyncresource [`Buffer`]: buffer.html +[`Buffer.allocUnsafe()`]: buffer.html#buffer_class_method_buffer_allocunsafe_size [`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`]: errors.html#errors_err_missing_message_port_in_transfer_list [`ERR_WORKER_NOT_RUNNING`]: errors.html#ERR_WORKER_NOT_RUNNING [`EventEmitter`]: events.html |