Skip to content

Commit ac8e90a

Browse files
gurgundayaduh95
authored andcommitted
buffer: speed up concat via TypedArray#set
PR-URL: #60399 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]>
1 parent 2b696ff commit ac8e90a

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

‎lib/buffer.js‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ function copyImpl(source, target, targetStart, sourceStart, sourceEnd){
242242
return_copyActual(source,target,targetStart,sourceStart,sourceEnd);
243243
}
244244

245-
function_copyActual(source,target,targetStart,sourceStart,sourceEnd){
245+
function_copyActual(source,target,targetStart,sourceStart,sourceEnd,isUint8Copy=false){
246246
if(sourceEnd-sourceStart>target.byteLength-targetStart)
247247
sourceEnd=sourceStart+target.byteLength-targetStart;
248248

@@ -254,7 +254,11 @@ function _copyActual(source, target, targetStart, sourceStart, sourceEnd){
254254
if(nb<=0)
255255
return0;
256256

257-
_copy(source,target,targetStart,sourceStart,nb);
257+
if(sourceStart===0&&nb===sourceLen&&(isUint8Copy||isUint8Array(target))){
258+
TypedArrayPrototypeSet(target,source,targetStart);
259+
}else{
260+
_copy(source,target,targetStart,sourceStart,nb);
261+
}
258262

259263
returnnb;
260264
}
@@ -612,7 +616,7 @@ Buffer.concat = function concat(list, length){
612616
thrownewERR_INVALID_ARG_TYPE(
613617
`list[${i}]`,['Buffer','Uint8Array'],list[i]);
614618
}
615-
pos+=_copyActual(buf,buffer,pos,0,buf.length);
619+
pos+=_copyActual(buf,buffer,pos,0,buf.length,true);
616620
}
617621

618622
// Note: `length` is always equal to `buffer.length` at this point

‎test/parallel/test-buffer-concat.js‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ assert.throws(() =>{
7676
constrandom10=common.hasCrypto ?
7777
require('crypto').randomBytes(10) :
7878
Buffer.alloc(10,1);
79+
constderived18=Buffer.alloc(18);
80+
for(leti=0,j=0;i<18;i++){
81+
if(i<10)
82+
derived18[i]=random10[i];
83+
else
84+
derived18[i]=random10[j++];
85+
}
7986
constempty=Buffer.alloc(0);
8087

8188
assert.notDeepStrictEqual(random10,empty);
@@ -85,6 +92,7 @@ assert.deepStrictEqual(Buffer.concat([], 100), empty);
8592
assert.deepStrictEqual(Buffer.concat([random10],0),empty);
8693
assert.deepStrictEqual(Buffer.concat([random10],10),random10);
8794
assert.deepStrictEqual(Buffer.concat([random10,random10],10),random10);
95+
assert.deepStrictEqual(Buffer.concat([random10,random10],18),derived18);
8896
assert.deepStrictEqual(Buffer.concat([empty,random10]),random10);
8997
assert.deepStrictEqual(Buffer.concat([random10,empty,empty]),random10);
9098

‎test/parallel/test-buffer-copy.js‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,23 @@ b.copy(c, 'not a valid offset');
226226
// Make sure this acted like a regular copy with `0` offset.
227227
assert.deepStrictEqual(c,b.slice(0,c.length));
228228

229+
// Copy into a Uint16Array target; bytes are packed into 16-bit elements.
230+
{
231+
constx=newUint16Array(4);
232+
constbuf=Buffer.of(1,2,3,4);
233+
constcopied=buf.copy(x);
234+
assert.strictEqual(copied,4);
235+
assert.ok(xinstanceofUint16Array);
236+
constbytes=newUint8Array(x.buffer,x.byteOffset,4);
237+
assert.deepStrictEqual(Array.from(bytes),[1,2,3,4]);
238+
constremaining=newUint8Array(
239+
x.buffer,
240+
x.byteOffset+4,
241+
x.byteLength-4
242+
);
243+
assert.ok(remaining.every((b)=>b===0));
244+
}
245+
229246
{
230247
c.fill('C');
231248
assert.throws(()=>{

0 commit comments

Comments
(0)