-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use %TypedArray%.prototype.subarray for Buffer.prototype.slice #17431
Comments
A fairer benchmark with mostly proper 'use strict';
if (typeof console === 'undefined') console = { log: print };
const N = 1e7;
// https://tc39.github.io/ecma262/#sec-speciesconstructor
function getSpeciesConstructor(o, defaultConstructor) {
const C = o.constructor;
if (C === undefined) return defaultConstructor;
if (typeof C !== 'function' && typeof C !== 'object') throw new TypeError();
const S = o[Symbol.species];
if (S === undefined || S === null) return defaultConstructor;
// Spec says IsConstructor, but a simpler test is used here instead.
if (typeof S === 'function') return S;
throw new TypeError();
}
function adjustOffset(offset, length) {
// Use Math.trunc() to convert offset to an integer value that can be larger
// than an Int32. Hence, don't use offset | 0 or similar techniques.
offset = Math.trunc(offset);
// `x !== x`-style conditionals are a faster form of `isNaN(x)`
if (offset === 0 || offset !== offset) {
return 0;
} else if (offset < 0) {
offset += length;
return offset > 0 ? offset : 0;
} else {
return offset < length ? offset : length;
}
}
class Buffer extends Uint8Array {
customSubarray(begin, end) {
const srcLength = this.length;
const beginIndex = adjustOffset(begin, srcLength);
const endIndex = end !== undefined ? adjustOffset(end, srcLength) : srcLength;
const newLength = endIndex > beginIndex ? endIndex - beginIndex : 0;
const beginByteOffset = this.byteOffset + beginIndex * this.BYTES_PER_ELEMENT;
return new (getSpeciesConstructor(this, this.constructor))(this.buffer, beginByteOffset, newLength);
}
}
Buffer.prototype[Symbol.species] = Buffer;
function testCustomSubarray(o) {
let result = 0;
for (let i = 0; i < N; ++i) {
result += o.customSubarray(3, 4).length;
}
return result;
}
function testSubarray(o) {
let result = 0;
for (let i = 0; i < N; ++i) {
result += o.subarray(3, 4).length;
}
return result;
}
var TESTS = [
testCustomSubarray,
testSubarray
];
const array = new Buffer(0x68, 0x65, 0x6c, 0x6c, 0x6f);
for (var j = 0; j < TESTS.length; j++) {
TESTS[j](array);
}
for (var j = 0; j < TESTS.length; j++) {
var startTime = Date.now();
TESTS[j](array);
console.log(TESTS[j].name + ':', (Date.now() - startTime), 'ms.');
} Still shows
|
Upstream bug: v8:7161 |
Upstream bug is considered fixed but there is still a significant difference:
|
I see similar results locally in ToT d8. Reopening the upstream bug. |
@TimothyGu .. is this still relevant? Does it need to remain open? |
Still pretty slow with Node.js v14
|
What about now? |
Is this still an issue? |
Currently, our implementation of
Buffer.prototype.slice()
operates identically toTypedArray.prototype.subarray()
(spec) down to the last minutia (with the assumption thatthis
is indeed aBuffer
, andBuffer[Symbol.species]
has not been tampered with). Ideally, we should just setBuffer.prototype.slice
toUint8Array.prototype.subarray
instead of reimplementing it. The only problem is performance:subarray()
is much slower thanslice()
:diff
I'd like to work with the V8 team to resolve the performance problem, and eventually use the language built-in for
Buffer.prototype.slice
./cc @bmeurer
The text was updated successfully, but these errors were encountered: