buffer: optimize buffer.concat performance · nodejs/node@940b58c
@@ -51,6 +51,7 @@ const {
5151 TypedArrayPrototypeGetLength,
5252 TypedArrayPrototypeSet,
5353 TypedArrayPrototypeSlice,
54+ TypedArrayPrototypeSubarray,
5455 Uint8Array,
5556} = primordials;
5657@@ -614,25 +615,55 @@ Buffer.concat = function concat(list, length) {
614615if (length === undefined) {
615616length = 0;
616617for (let i = 0; i < list.length; i++) {
617-if (list[i].length) {
618-length += list[i].length;
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 += TypedArrayPrototypeGetByteLength(buf);
620626}
621-} else {
622-validateOffset(length, 'length');
627+628+const buffer = allocate(length);
629+let pos = 0;
630+for (let i = 0; i < list.length; i++) {
631+const buf = list[i];
632+const bufLength = TypedArrayPrototypeGetByteLength(buf);
633+TypedArrayPrototypeSet(buffer, buf, pos);
634+pos += bufLength;
635+}
636+637+if (pos < length) {
638+TypedArrayPrototypeFill(buffer, 0, pos, length);
639+}
640+return buffer;
623641}
624642625-const buffer = Buffer.allocUnsafe(length);
626-let pos = 0;
643+validateOffset(length, 'length');
627644for (let i = 0; i < list.length; i++) {
628-const buf = list[i];
629-if (!isUint8Array(buf)) {
645+if (!isUint8Array(list[i])) {
630646// TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE.
631647// Instead, find the proper error code for this.
632648throw new ERR_INVALID_ARG_TYPE(
633649`list[${i}]`, ['Buffer', 'Uint8Array'], list[i]);
634650}
635-pos += _copyActual(buf, buffer, pos, 0, buf.length, true);
651+}
652+653+const buffer = allocate(length);
654+let pos = 0;
655+for (let i = 0; i < list.length; i++) {
656+const buf = list[i];
657+const bufLength = TypedArrayPrototypeGetByteLength(buf);
658+if (pos + bufLength > length) {
659+TypedArrayPrototypeSet(buffer,
660+TypedArrayPrototypeSubarray(buf, 0, length - pos),
661+pos);
662+pos = length;
663+break;
664+}
665+TypedArrayPrototypeSet(buffer, buf, pos);
666+pos += bufLength;
636667}
637668638669// Note: `length` is always equal to `buffer.length` at this point