Skip to content

Commit 7ded458

Browse files
committed
buffer: optimize buffer.concat performance
1 parent 3ab9dd8 commit 7ded458

1 file changed

Lines changed: 36 additions & 14 deletions

File tree

lib/buffer.js

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -608,38 +608,60 @@ Buffer[kIsEncodingSymbol] = Buffer.isEncoding;
608608
Buffer.concat = function concat(list, length) {
609609
validateArray(list, 'list');
610610

611-
if (list.length === 0)
611+
const listLen = list.length;
612+
if (listLen === 0)
612613
return new FastBuffer();
613614

614615
if (length === undefined) {
615616
length = 0;
616-
for (let i = 0; i < list.length; i++) {
617-
if (list[i].length) {
618-
length += list[i].length;
617+
for (let i = 0; i < listLen; i++) {
618+
const buf = list[i];
619+
if (!isUint8Array(buf)) {
620+
// TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE.
621+
// Instead, find the proper error code for this.
622+
throw new ERR_INVALID_ARG_TYPE(
623+
`list[${i}]`, ['Buffer', 'Uint8Array'], buf);
619624
}
625+
length += buf.length;
620626
}
621-
} else {
622-
validateOffset(length, 'length');
627+
628+
const buffer = allocate(length);
629+
let pos = 0;
630+
for (let i = 0; i < listLen; i++) {
631+
const buf = list[i];
632+
TypedArrayPrototypeSet(buffer, buf, pos);
633+
pos += buf.length;
634+
}
635+
636+
if (pos < length) {
637+
TypedArrayPrototypeFill(buffer, 0, pos, length);
638+
}
639+
return buffer;
623640
}
624641

625-
const buffer = Buffer.allocUnsafe(length);
642+
validateOffset(length, 'length');
643+
const buffer = allocate(length);
626644
let pos = 0;
627-
for (let i = 0; i < list.length; i++) {
645+
for (let i = 0; i < listLen; i++) {
628646
const buf = list[i];
629647
if (!isUint8Array(buf)) {
630648
// TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE.
631649
// Instead, find the proper error code for this.
632650
throw new ERR_INVALID_ARG_TYPE(
633-
`list[${i}]`, ['Buffer', 'Uint8Array'], list[i]);
651+
`list[${i}]`, ['Buffer', 'Uint8Array'], buf);
652+
}
653+
if (pos + buf.length > length) {
654+
TypedArrayPrototypeSet(buffer,
655+
TypedArrayPrototypeSlice(buf, 0, length - pos),
656+
pos);
657+
pos = length;
658+
break;
634659
}
635-
pos += _copyActual(buf, buffer, pos, 0, buf.length, true);
660+
TypedArrayPrototypeSet(buffer, buf, pos);
661+
pos += buf.length;
636662
}
637663

638-
// Note: `length` is always equal to `buffer.length` at this point
639664
if (pos < length) {
640-
// Zero-fill the remaining bytes if the specified `length` was more than
641-
// the actual total length, i.e. if we have some remaining allocated bytes
642-
// there were not initialized.
643665
TypedArrayPrototypeFill(buffer, 0, pos, length);
644666
}
645667

0 commit comments

Comments
 (0)