Skip to content

Commit 0a5f80a

Browse files
skomskiFishrock123
authored andcommitted
src: use subarray() in Buffer#slice() for speedup
Use the built-in Typed Array method subarray() to improve performance of Buffer#slice(). Benchmark improvements: benchmark/buffer-slice: 40% benchmark/buffer-creation (pool): 25% Additional tests also added. PR-URL: #2777 Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Сковорода Никита Андреевич <[email protected]>
1 parent ba47511 commit 0a5f80a

File tree

3 files changed

+37
-50
lines changed

3 files changed

+37
-50
lines changed

lib/buffer.js

+5-26
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function allocate(size) {
7373
if (size < (Buffer.poolSize >>> 1)) {
7474
if (size > (poolSize - poolOffset))
7575
createPool();
76-
var b = binding.slice(allocPool, poolOffset, poolOffset + size);
76+
var b = allocPool.slice(poolOffset, poolOffset + size);
7777
poolOffset += size;
7878
alignPool();
7979
return b;
@@ -94,7 +94,7 @@ function fromString(string, encoding) {
9494
if (length > (poolSize - poolOffset))
9595
createPool();
9696
var actual = allocPool.write(string, poolOffset, encoding);
97-
var b = binding.slice(allocPool, poolOffset, poolOffset + actual);
97+
var b = allocPool.slice(poolOffset, poolOffset + actual);
9898
poolOffset += actual;
9999
alignPool();
100100
return b;
@@ -552,30 +552,9 @@ Buffer.prototype.toJSON = function() {
552552
// TODO(trevnorris): currently works like Array.prototype.slice(), which
553553
// doesn't follow the new standard for throwing on out of range indexes.
554554
Buffer.prototype.slice = function slice(start, end) {
555-
var len = this.length;
556-
start = ~~start;
557-
end = end === undefined ? len : ~~end;
558-
559-
if (start < 0) {
560-
start += len;
561-
if (start < 0)
562-
start = 0;
563-
} else if (start > len) {
564-
start = len;
565-
}
566-
567-
if (end < 0) {
568-
end += len;
569-
if (end < 0)
570-
end = 0;
571-
} else if (end > len) {
572-
end = len;
573-
}
574-
575-
if (end < start)
576-
end = start;
577-
578-
return binding.slice(this, start, end);
555+
const buffer = this.subarray(start, end);
556+
Object.setPrototypeOf(buffer, Buffer.prototype);
557+
return buffer;
579558
};
580559

581560

src/node_buffer.cc

-24
Original file line numberDiff line numberDiff line change
@@ -456,29 +456,6 @@ void CreateFromArrayBuffer(const FunctionCallbackInfo<Value>& args) {
456456
}
457457

458458

459-
void Slice(const FunctionCallbackInfo<Value>& args) {
460-
CHECK(args[0]->IsUint8Array());
461-
CHECK(args[1]->IsNumber());
462-
CHECK(args[2]->IsNumber());
463-
Environment* env = Environment::GetCurrent(args);
464-
Local<Uint8Array> ab_ui = args[0].As<Uint8Array>();
465-
Local<ArrayBuffer> ab = ab_ui->Buffer();
466-
ArrayBuffer::Contents ab_c = ab->GetContents();
467-
size_t offset = ab_ui->ByteOffset();
468-
size_t start = args[1]->NumberValue() + offset;
469-
size_t end = args[2]->NumberValue() + offset;
470-
CHECK_GE(end, start);
471-
size_t size = end - start;
472-
CHECK_GE(ab_c.ByteLength(), start + size);
473-
Local<Uint8Array> ui = Uint8Array::New(ab, start, size);
474-
Maybe<bool> mb =
475-
ui->SetPrototype(env->context(), env->buffer_prototype_object());
476-
if (!mb.FromMaybe(false))
477-
return env->ThrowError("Unable to set Object prototype");
478-
args.GetReturnValue().Set(ui);
479-
}
480-
481-
482459
template <encoding encoding>
483460
void StringSlice(const FunctionCallbackInfo<Value>& args) {
484461
Environment* env = Environment::GetCurrent(args);
@@ -1002,7 +979,6 @@ void Initialize(Local<Object> target,
1002979
env->SetMethod(target, "createFromString", CreateFromString);
1003980
env->SetMethod(target, "createFromArrayBuffer", CreateFromArrayBuffer);
1004981

1005-
env->SetMethod(target, "slice", Slice);
1006982
env->SetMethod(target, "byteLengthUtf8", ByteLengthUtf8);
1007983
env->SetMethod(target, "compare", Compare);
1008984
env->SetMethod(target, "fill", Fill);

test/parallel/test-buffer.js

+32
Original file line numberDiff line numberDiff line change
@@ -1061,14 +1061,46 @@ assert.equal(buf.readInt8(0), -1);
10611061
assert.equal(buf.slice(-10, 10), '0123456789');
10621062
assert.equal(buf.slice(-20, 10), '0123456789');
10631063
assert.equal(buf.slice(-20, -10), '');
1064+
assert.equal(buf.slice(), '0123456789');
1065+
assert.equal(buf.slice(0), '0123456789');
1066+
assert.equal(buf.slice(0, 0), '');
1067+
assert.equal(buf.slice(undefined), '0123456789');
1068+
assert.equal(buf.slice('foobar'), '0123456789');
1069+
assert.equal(buf.slice(undefined, undefined), '0123456789');
1070+
1071+
assert.equal(buf.slice(2), '23456789');
1072+
assert.equal(buf.slice(5), '56789');
1073+
assert.equal(buf.slice(10), '');
1074+
assert.equal(buf.slice(5, 8), '567');
1075+
assert.equal(buf.slice(8, -1), '8');
1076+
assert.equal(buf.slice(-10), '0123456789');
1077+
assert.equal(buf.slice(0, -9), '0');
1078+
assert.equal(buf.slice(0, -10), '');
10641079
assert.equal(buf.slice(0, -1), '012345678');
10651080
assert.equal(buf.slice(2, -2), '234567');
10661081
assert.equal(buf.slice(0, 65536), '0123456789');
10671082
assert.equal(buf.slice(65536, 0), '');
1083+
assert.equal(buf.slice(-5, -8), '');
1084+
assert.equal(buf.slice(-5, -3), '56');
1085+
assert.equal(buf.slice(-10, 10), '0123456789');
10681086
for (var i = 0, s = buf.toString(); i < buf.length; ++i) {
1087+
assert.equal(buf.slice(i), s.slice(i));
1088+
assert.equal(buf.slice(0, i), s.slice(0, i));
10691089
assert.equal(buf.slice(-i), s.slice(-i));
10701090
assert.equal(buf.slice(0, -i), s.slice(0, -i));
10711091
}
1092+
1093+
var utf16Buf = new Buffer('0123456789', 'utf16le');
1094+
assert.deepEqual(utf16Buf.slice(0, 6), Buffer('012', 'utf16le'));
1095+
1096+
assert.equal(buf.slice('0', '1'), '0');
1097+
assert.equal(buf.slice('-5', '10'), '56789');
1098+
assert.equal(buf.slice('-10', '10'), '0123456789');
1099+
assert.equal(buf.slice('-10', '-5'), '01234');
1100+
assert.equal(buf.slice('-10', '-0'), '');
1101+
assert.equal(buf.slice('111'), '');
1102+
assert.equal(buf.slice('0', '-111'), '');
1103+
10721104
// try to slice a zero length Buffer
10731105
// see https://github.com/joyent/node/issues/5881
10741106
SlowBuffer(0).slice(0, 1);

0 commit comments

Comments
 (0)