Skip to content

Commit f928746

Browse files
mscdexMylesBorins
authored andcommitted
stream: avoid additional validation for Buffers
These changes result in ~50% improvement in the included benchmark. PR-URL: #10580 Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent de22ff6 commit f928746

2 files changed

Lines changed: 40 additions & 20 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
constWritable=require('stream').Writable;
5+
6+
constbench=common.createBenchmark(main,{
7+
n: [2e6]
8+
});
9+
10+
functionmain(conf){
11+
constn=+conf.n;
12+
constb=Buffer.allocUnsafe(1024);
13+
consts=newWritable();
14+
s._write=function(chunk,encoding,cb){
15+
cb();
16+
};
17+
18+
bench.start();
19+
for(vark=0;k<n;++k){
20+
s.write(b);
21+
}
22+
bench.end(n);
23+
}

‎lib/_stream_writable.js‎

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -196,23 +196,18 @@ function writeAfterEnd(stream, cb) {
196196
process.nextTick(cb,er);
197197
}
198198

199-
// If we get something that is not a buffer, string, null, or undefined,
200-
// and we're not in objectMode, then that's an error.
201-
// Otherwise stream chunks are all considered to be of length=1, and the
202-
// watermarks determine how many objects to keep in the buffer, rather than
203-
// how many bytes or characters.
199+
// Checks that a user-supplied chunk is valid, especially for the particular
200+
// mode the stream is in. Currently this means that `null` is never accepted
201+
// and undefined/non-string values are only allowed in object mode.
204202
functionvalidChunk(stream,state,chunk,cb){
205203
varvalid=true;
206204
varer=false;
207-
// Always throw error if a null is written
208-
// if we are not in object mode then throw
209-
// if it is not a buffer, string, or undefined.
205+
210206
if(chunk===null){
211207
er=newTypeError('May not write null values to stream');
212-
}elseif(!(chunkinstanceofBuffer)&&
213-
typeofchunk!=='string'&&
214-
chunk!==undefined&&
215-
!state.objectMode){
208+
}elseif(typeofchunk!=='string'&&
209+
chunk!==undefined&&
210+
!state.objectMode){
216211
er=newTypeError('Invalid non-string/buffer chunk');
217212
}
218213
if(er){
@@ -226,13 +221,14 @@ function validChunk(stream, state, chunk, cb) {
226221
Writable.prototype.write=function(chunk,encoding,cb){
227222
varstate=this._writableState;
228223
varret=false;
224+
varisBuf=(chunkinstanceofBuffer);
229225

230226
if(typeofencoding==='function'){
231227
cb=encoding;
232228
encoding=null;
233229
}
234230

235-
if(chunkinstanceofBuffer)
231+
if(isBuf)
236232
encoding='buffer';
237233
elseif(!encoding)
238234
encoding=state.defaultEncoding;
@@ -242,9 +238,9 @@ Writable.prototype.write = function(chunk, encoding, cb) {
242238

243239
if(state.ended)
244240
writeAfterEnd(this,cb);
245-
elseif(validChunk(this,state,chunk,cb)){
241+
elseif(isBuf||validChunk(this,state,chunk,cb)){
246242
state.pendingcb++;
247-
ret=writeOrBuffer(this,state,chunk,encoding,cb);
243+
ret=writeOrBuffer(this,state,isBuf,chunk,encoding,cb);
248244
}
249245

250246
returnret;
@@ -293,11 +289,12 @@ function decodeChunk(state, chunk, encoding) {
293289
// if we're already writing something, then just put this
294290
// in the queue, and wait our turn. Otherwise, call _write
295291
// If we return false, then we need a drain event, so set that flag.
296-
functionwriteOrBuffer(stream,state,chunk,encoding,cb){
297-
chunk=decodeChunk(state,chunk,encoding);
298-
299-
if(chunkinstanceofBuffer)
300-
encoding='buffer';
292+
functionwriteOrBuffer(stream,state,isBuf,chunk,encoding,cb){
293+
if(!isBuf){
294+
chunk=decodeChunk(state,chunk,encoding);
295+
if(chunkinstanceofBuffer)
296+
encoding='buffer';
297+
}
301298
varlen=state.objectMode ? 1 : chunk.length;
302299

303300
state.length+=len;

0 commit comments

Comments
 (0)