src,buffer: allow heap-allocated typed arrays
I noticed that the reason we’ve been disabling this has not actually been true, so it seems to make sense to let the engine use its default values. /cc @nodejs/buffer @nodejs/v8
build: remove v8_typed_array_max_size_in_heap option
This was added in 16f86d6c, based on
the assumption that otherwise, the memory behind ArrayBuffer
instances could be moved around on the heap while native code
holds references to it.
This does not match what V8 actually does (and also did at the time):
- The option/build variable was about always only about TypedArrays,
not ArrayBuffers. Calls like
new ArrayBuffer(4)
call into C++ regardless of the option value, but calls likenew Uint8Array(4)
would not call into C++ under V8 defaults. - When first accessing a heap-allocated TypedArray’s
ArrayBuffer
, whether that is through the JS.buffer
getter or the C++ArrayBufferView::Buffer()
function, a copy of the contents is created using the ArrayBuffer allocator and stored as the (permanent, unmovable) backing store.
As a consequence, the memory returned by ArrayBuffer::GetContents()
is not moved around, because it is fixed once the ArrayBuffer
object itself first comes into explicit existence in any way.
Removing this build option significantly speeds up creation of typed arrays from JS:
$ ./node benchmark/compare.js --new ./node --old ./node-master --runs 10 --filter buffer-creation.js buffers | Rscript benchmark/compare.R
confidence improvement accuracy (*) (**) (***)
buffers/buffer-creation.js n=1024 len=10 type='buffer()' *** 593.66 % ±28.64% ±41.10% ±60.36%
buffers/buffer-creation.js n=1024 len=10 type='fast-alloc-fill' *** 675.42 % ±90.67% ±130.24% ±191.54%
buffers/buffer-creation.js n=1024 len=10 type='fast-alloc' *** 663.55 % ±58.41% ±83.87% ±123.29%
[... see commit log for more, statistically insignificant results ...]
The performance gains effect are undone once native code accesses
the underlying ArrayBuffer, but then again that a) does not happen for
all TypedArrays, and b) it should also make sense to look into using
ArrayBufferView::CopyContents()
in some places, which is made
specifically to avoid such a performance impact and allows us to
use the benefits of heap-allocated typed arrays.
Refs: https://github.com/nodejs/node/commit/16f86d6c578ff7aec708c7d736558a199d290e9c Refs: https://github.com/nodejs/node/pull/2893 Refs: https://github.com/nodejs/node/commit/74178a5682958d499896e0fa1af6bc0321ec1935#commitcomment-13250880 Refs: http://logs.libuv.org/node-dev/2015-09-15
src: allow not materializing ArrayBuffers from C++
Where appropriate, use a helper that wraps around
ArrayBufferView::Buffer()
or ArrayBufferView::CopyContents()
rather than Buffer::Data()
, as that may help to avoid materializing
the underlying ArrayBuffer
when reading small typed arrays from C++.
This allows keeping the performance benefits of the faster creation of
heap-allocated small typed arrays in many cases.
buffer: avoid materializing ArrayBuffer for creation
Do not create an ArrayBuffer
if the engine’s settings avoid it
and we don’t need it.
test: verify heap buffer allocations occur
Check that small typed arrays, including Buffer
s (unless allocated
by Buffer.allocUnsafe()
), are indeed heap-allocated.
Checklist
-
make -j4 test
(UNIX), orvcbuild test
(Windows) passes -
tests and/or benchmarks are included -
commit message follows commit guidelines