buffer: optimize Buffer.prototype.copy#63828
Open
ronag wants to merge 2 commits into
Open
Conversation
Collaborator
|
Review requested:
|
0e2e646 to
1eb628a
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates Node’s Buffer.prototype.copy() implementation to use V8’s new ArrayBuffer::CopyArrayBufferBytes / SharedArrayBuffer::CopyArrayBufferBytes APIs, improving performance for partial copies and ensuring detached/immutable targets become no-op copies that report 0 bytes copied.
Changes:
- Route the native
_copybinding through V8’s newCopyArrayBufferBytesAPI (including relaxed-atomic handling when both sides areSharedArrayBuffer-backed). - Update JS-side
copy()to return the actual number of bytes copied (as reported by the native binding), including0for immutable/detached targets. - Add test coverage for
SharedArrayBuffercopies and immutableArrayBuffertargets, plus V8 cctests and API header/docs updates.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/parallel/test-buffer-copy.js | Adds SharedArrayBuffer copy coverage (including overlap + byteOffset cases). |
| test/parallel/test-buffer-copy-immutable.js | Adds coverage for copying into immutable ArrayBuffer-backed targets (expects 0 bytes copied). |
| src/node_buffer.cc | Reworks native copy to call V8 CopyArrayBufferBytes and return actual copied byte count. |
| lib/buffer.js | Simplifies JS copy path to rely on native _copy return value for bytes-copied semantics. |
| deps/v8/test/cctest/test-api-array-buffer.cc | Adds V8 cctests for the new CopyArrayBufferBytes APIs (detached + immutable cases). |
| deps/v8/src/api/api.cc | Implements ArrayBuffer::CopyArrayBufferBytes and SharedArrayBuffer::CopyArrayBufferBytes. |
| deps/v8/include/v8-array-buffer.h | Exposes the new public V8 API methods and documents their behavior. |
| common.gypi | Bumps v8_embedder_string to reflect the added floating V8 patch. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
1eb628a to
8bd6850
Compare
Member
|
can you split the v8 patch commit and the implementation commit? |
Add v8::ArrayBuffer::CopyArrayBufferBytes and
v8::SharedArrayBuffer::CopyArrayBufferBytes, which copy a byte range
from one backing store to another. V8 clamps the byte range and handles
detached and immutable buffers: nothing is copied when the source is
detached or the target is detached or immutable, and the number of bytes
actually copied is returned. The SharedArrayBuffer overload uses a
relaxed-atomic memmove that honors the SharedArrayBuffer memory model.
Carried as a floating patch cherry-picked from:
https://chromium-review.googlesource.com/c/v8/v8/+/7735151
That CL is authored by a Node.js collaborator (Ben Noordhuis) and is
expected to land upstream, so the floating patch should be easy to
maintain: it touches nothing but the public ArrayBuffer API and can be
dropped wholesale on the next V8 upgrade that includes it.
v8_embedder_string is bumped to -node.21 accordingly.
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/7735151
Signed-off-by: Robert Nagy <ronagy@icloud.com>
8bd6850 to
5cb3967
Compare
anonrig
approved these changes
Jun 10, 2026
Renegade334
reviewed
Jun 10, 2026
Route the native backing of Buffer.prototype.copy (CopyImpl, the `_copy` binding) through V8's new v8::ArrayBuffer::CopyArrayBufferBytes API (added in the preceding commit) instead of materializing an ArrayBufferViewContents and doing a manual memmove. This speeds up partial copies (sourceStart > 0). All copies now go through this binding: the previous %TypedArray%.prototype.set fast-path for whole-buffer copies is dropped, since it would throw on a detached or immutable target rather than report a 0-byte no-op, and the benchmarks below show the native path is comparable for that case. When both sides are backed by a SharedArrayBuffer the relaxed-atomic overload is used, which honors the SharedArrayBuffer memory model. Mixed copies (one SharedArrayBuffer, one ArrayBuffer) use the regular overload. copy() now reports the number of bytes actually copied, as returned by V8: 0 when the target is backed by a detached or immutable ArrayBuffer. The copy is then a no-op rather than a write to read-only memory. The native binding now plumbs byte offsets and the copied-byte count through as size_t, passed across the fast/slow API boundary as doubles (exact for integer values below 2^53), so copies that cross the 4 GiB boundary are no longer truncated to 32 bits. buffer-copy.js vs node v26.3.0 (x64, 30 runs): partial=false bytes=1024: +7.91% (***) partial=false bytes=128: +0.17% partial=false bytes=8: -0.89% partial=true bytes=1024: +22.33% (***) partial=true bytes=128: +19.58% (***) partial=true bytes=8: +18.70% (***) This supersedes the prototype in nodejs#62491, which added a bespoke ArrayBufferView::FastCopy instead of using the upstream-friendly CopyArrayBufferBytes API. Adds SharedArrayBuffer and immutable-ArrayBuffer coverage to the buffer copy tests, plus a pummel regression test for copies larger than 2^32 bytes. Refs: nodejs#55422 Signed-off-by: Robert Nagy <ronagy@icloud.com> Assisted-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5cb3967 to
da189fb
Compare
Member
For posterity, said CL was merged upstream earlier today. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Route the native backing of Buffer.prototype.copy (CopyImpl, the
_copybinding) through V8's new v8::ArrayBuffer::CopyArrayBufferBytes API instead of materializing an ArrayBufferViewContents and doing a manual memmove. This speeds up partial copies (sourceStart > 0). All copies now go through this binding: the previous %TypedArray%.prototype.set fast-path for whole-buffer copies is dropped, since it would throw on a detached or immutable target rather than report a 0-byte no-op, and the benchmarks below show the native path is comparable for that case.V8 clamps the byte range and handles detached and immutable buffers. When both sides are backed by a SharedArrayBuffer the relaxed-atomic overload is used, which honors the SharedArrayBuffer memory model. Mixed copies (one SharedArrayBuffer, one ArrayBuffer) use the regular overload.
copy() now reports the number of bytes actually copied, as returned by V8: 0 when the target is backed by a detached or immutable ArrayBuffer. The copy is then a no-op rather than a write to read-only memory.
buffer-copy.js vs node v26.3.0 (x64, 30 runs):
partial=false bytes=1024: +7.91% ()
partial=false bytes=128: +0.17%
partial=false bytes=8: -0.89%
partial=true bytes=1024: +22.33% ()
partial=true bytes=128: +19.58% ()
partial=true bytes=8: +18.70% ()
The V8 API is carried as a floating patch cherry-picked from:
That CL is authored by a Node.js collaborator (Ben Noordhuis) and is expected to land upstream, so the floating patch should be easy to maintain: it touches nothing but the public ArrayBuffer API and can be dropped wholesale on the next V8 upgrade that includes it. v8_embedder_string is bumped to -node.21 accordingly.
This supersedes the prototype in
#62491, which added a bespoke ArrayBufferView::FastCopy instead of using the upstream-friendly CopyArrayBufferBytes API.
Adds SharedArrayBuffer and immutable-ArrayBuffer coverage to the buffer copy tests.
Assisted-by: Claude Opus 4.8 (1M context) noreply@anthropic.com