This is commit 01ee551, except for the DataView type this time.
Make the behavior of DataView consistent with that of typed arrays:
make a copy of the backing store.
Follow browser behavior, only share the backing store when it's a
ArrayBuffer. That is:
var abuf = new ArrayBuffer(32);
var a = new Int8Array(abuf);
var b = new Int8Array(abuf);
a[0] = 0;
b[0] = 1;
assert(a[0] === b[0]); // a and b share memory
But:
var a = new Int8Array(32);
var b = new Int8Array(a);
a[0] = 0;
b[0] = 1;
assert(a[0] !== b[0]); // a and b don't share memory
The typed arrays spec allows both `a[0] === b[0]` and `a[0] !=== b[0]`
but Chrome and Firefox implement the behavior where memory is not
shared.
Copying the memory is less efficient but let's do it anyway for the
sake of the Principle of Least Surprise.
Fixes#4714.
Inform V8 that the zlib context object is tied to a large off-heap buffer.
This makes the GC run more often (in theory) and improves the accuracy of
--trace_external_memory.
In zlibBuffer(), don't wait for the garbage collector to reclaim the zlib memory
but release it manually. Reduces memory consumption by a factor of 10 or more
with some workloads.
Test case:
function f() {
require('zlib').deflate('xxx', g);
}
function g() {
setTimeout(f, 5);
}
f();
Observe RSS memory usage with and without this commit. After 10,000 iterations,
RSS stabilizes at ~35 MB with this commit. Without, RSS is over 300 MB and keeps
growing.
Cause: whenever the JS object heap hits the high-water mark, the V8 GC sweeps
it clean, then tries to grow it in order to avoid more sweeps in the near
future. Rule of thumb: the bigger the JS heap, the lazier the GC can be.
A side effect of a bigger heap is that objects now live longer. This is harmless
in general but it affects zlib context objects because those are tied to large
buffers that live outside the JS heap, on the order of 16K per context object.
Ergo, don't wait for the GC to reclaim the memory - it may take a long time.
Fixes#4172.
Move the implementation to C++ land. This is similar to commit 3f65916
but this time for the write() function and the Buffer(s, 'hex')
constructor.
Speeds up the benchmark below about 24x (2.6s vs 1:02m).
var s = 'f';
for (var i = 0; i < 26; ++i) s += s; // 64 MB
Buffer(s, 'hex');
If the NODE_DEBUGGER_TIMEOUT environment variable is set, then use
that as the number of ms to wait for the debugger to start.
This is primarily to work around a race condition that almost never
happens in real usage with the debugger, but happens EVERY FRACKING
TIME when the debugger tests run as part of 'make test'.
Move the implementation to C++ land. The old JS implementation used
string concatenation, was dog slow and consumed copious amounts of
memory for large buffers. Example:
var buf = Buffer(0x1000000); // 16 MB
buf.toString('hex') // Used 3+ GB of memory.
The new implementation operates in O(n) time and space.
Fixes#4700.
If the end argument is omitted or not a number, make it default to
the end of the buffer, not zero.
Ideally, it should not matter what it defaults to because the JS shim
in lib/buffer.js should handle that but there are still several places
in node.js core that secrete SlowBuffers, hence Buffer::Copy() gets
called without going through Buffer.prototype.copy() first.
It's segfaulting in release mode and asserting in debug mode:
#
# Fatal error in ../../deps/v8/src/api.h, line 297
# CHECK(allow_empty_handle || that != __null) failed
#
This reverts commit 99f0b022d5.
Before sending handle to another process using uv_write2(), it should be
referenced to prevent it from being GCed before AfterWrite() will be
called.
see #4599
mainly to allow native addons to export single functions on
rather than being restricted to operating on an existing
object.
Init functions now receive exports as the first argument, like
before, but also the module object as the second argument, if they
support it.
Related to #4634
cc: @rvagg
* Omit ToObject() call. Buffer::Data() and Buffer::Length() know how
to deal with Values.
* Don't check if the argument is undefined because it realistically
never is and undefined->integer coercion achieves the same thing.
Fix issue where SlowBuffers couldn't be passed as target to Buffer
copy().
Also included checks to see if Argument parameters are defined before
assigning their values. This offered ~3x's performance gain.
Backport of 16bbecc from master branch. Closes#4633.
Changed types of errors thrown to be more indicative of what the error
represents. Also removed a few unnecessary uses of the v8 fully
quantified typename.
Fix issue where SlowBuffers couldn't be passed as target to Buffer
copy().
Also included checks to see if Argument parameters are defined before
assigning their values. This offered ~3x's performance gain.
* npm: Upgrade to v1.2.3
* V8: Upgrade to 3.15.11.10
* streams: Support objects other than Buffers (Jake Verbaten)
* buffer: remove float write range checks (Trevor Norris)
* http: close connection on 304/204 responses with chunked encoding (Ben Noordhuis)
* build: fix build with dtrace support on FreeBSD (Fedor Indutny)
* console: Support formatting options in trace() (isaacs)
* domain: empty stack on all exceptions (Dave Olszewski)
* unix, windows: make uv_*_bind() error codes consistent (Andrius Bentkus)
* linux: add futimes() fallback (Ben Noordhuis)
Removed range checks when writing float values, and removed a few
includes and defines. Also updated api docs to reflect that invalid 32
bit float is an unspecified behavior.
Fix an off-by-one error introduced in 9fe3734 that caused a regression
in the default endianness used for writes in DataView::setGeneric().
Fixes#4626.
Due to the nature of asyncronous programming, it's impossible to know
what will run on the next tick. Because of this, it's not correct to
maintain domain stack state between ticks
Since the _fatalException handler is only invoked after the stack is
unwound, once it exits the tick will end. The only reasonable thing to
do in that case is to exit *all* domains.
* V8: Upgrade to 3.15.11.7
* npm: Upgrade to 1.2.2
* punycode: Upgrade to 1.2.0 (Mathias Bynens)
* repl: make built-in modules available by default (Felix Böhm)
* windows: add support for '_Total' perf counters (Scott Blomquist)
* cluster: make --prof work for workers (Ben Noordhuis)
* child_process: do not keep list of sent sockets (Fedor Indutny)
* tls: Follow RFC6125 more strictly (Fedor Indutny)
* buffer: floating point read/write improvements (Trevor Norris)
* TypedArrays: Improve dataview perf without endian param (Dean McNamee)
* module: assert require() called with a non-empty string (Felix Böhm, James Campos)
* stdio: Set readable/writable flags properly (isaacs)
* stream: Properly handle large reads from push-streams (isaacs)
Reject negative offsets in SlowBuffer::MakeFastBuffer(), it allows
the creation of buffers that point to arbitrary addresses.
Reported by Trevor Norris.
V8 seems to be particularly slow converting an undefined value to false
in BooleanValue.
Revert this when we upgrade to V8 3.17, or whenever the fix discussed
in http://code.google.com/p/v8/issues/detail?id=2487 lands in V8.
Improvements:
* floating point operations are approx 4x's faster
* Now write quiet NaN's
* all read/write on floating point now done in C, so no more need for
lib/buffer_ieee754.js
* float values have more accurate min/max value checks
* add additional benchmarks for buffers read/write
* created benchmark/_bench_timer.js which is a simple library that
can be included into any benchmark and provides an intelligent tracker
for sync and async tests
* add benchmarks for DataView set methods
* add checks and tests to make sure offset is greater than 0
The int8_t and uint8_t typedefs on sunos/smartos depend on a number of
compiler directives. Avoid ambiguity and specify signed and unsigned
char explicitly.
Fixes the following build error:
../src/stream_wrap.cc: In static member function 'static void*
node::WriteWrap::operator new(size_t)':
../src/stream_wrap.cc:70:49: warning: no return statement in function
returning non-void [-Wreturn-type]
In file included from ../src/v8_typed_array.cc:26:0:
../src/v8_typed_array_bswap.h: In function 'T
v8_typed_array::SwapBytes(T) [with T = signed char]':
../src/v8_typed_array_bswap.h:150:23: instantiated from 'T
v8_typed_array::LoadAndSwapBytes(void*) [with T = signed char]'
../src/v8_typed_array.cc:694:7: instantiated from 'static
v8::Handle<v8::Value> {anonymous}::DataView::getGeneric(const
v8::Arguments&) [with T = signed char]'
../src/v8_typed_array.cc:738:40: instantiated from here
../src/v8_typed_array_bswap.h:125:16: error: size of array is
negative
Implement load and store swizzling operations. This reduces an unneeded
back and forth between types and additionally keeps the value in the
swappable type until it is swapped. This is important for correctness
when dealing with floating point, to avoid the possibility of loading
the bits of a signaling NaN (because it isn't yet swapped) into the FPU.
This additionally produces better code (comments are mine):
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
setValue<double>:
movd %xmm0, %rax ; fp reg -> gen reg
bswapq %rax ; 64-bit byte swap
movq %rax, (%r15,%r12) ; store
Implement swizzling with compiler intrinsics and be aware of the native
endianness to correctly swap on big endian machines.
This introduces a template function to swap the bytes of a value,
and macros for the low level swap (taking advantage of gcc and msvc
intrinsics). This produces code like the following (comments are mine):
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
setValue<double>:
movd %xmm0, %rax ; fp reg -> gen reg
bswapq %rax ; 64-bit byte swap
movd %rax, %xmm0 ; gen reg -> fp reg
movq %xmm0, (%r15,%r12) ; store