@@ -108,6 +108,14 @@ function WritableState(options, stream) {
108108
109109 // True if the error was already emitted and should not be thrown again
110110 this . errorEmitted = false ;
111+
112+ // count buffered requests
113+ this . bufferedRequestCount = 0 ;
114+
115+ // create the two objects needed to store the corked requests
116+ // they are not a linked list, as no new elements are inserted in there
117+ this . corkedRequestsFree = new CorkedRequest ( this ) ;
118+ this . corkedRequestsFree . next = new CorkedRequest ( this ) ;
111119}
112120
113121WritableState . prototype . getBuffer = function writableStateGetBuffer ( ) {
@@ -274,6 +282,7 @@ function writeOrBuffer(stream, state, chunk, encoding, cb) {
274282 } else {
275283 state . bufferedRequest = state . lastBufferedRequest ;
276284 }
285+ state . bufferedRequestCount += 1 ;
277286 } else {
278287 doWrite ( stream , state , false , len , chunk , encoding , cb ) ;
279288 }
@@ -357,34 +366,33 @@ function onwriteDrain(stream, state) {
357366 }
358367}
359368
360-
361369// if there's something in the buffer waiting, then process it
362370function clearBuffer ( stream , state ) {
363371 state . bufferProcessing = true ;
364372 var entry = state . bufferedRequest ;
365373
366374 if ( stream . _writev && entry && entry . next ) {
367375 // Fast case, write everything using _writev()
368- var buffer = [ ] ;
369- var cbs = [ ] ;
376+ var l = state . bufferedRequestCount ;
377+ var buffer = new Array ( l ) ;
378+ var holder = state . corkedRequestsFree ;
379+ holder . entry = entry ;
380+
381+ var count = 0 ;
370382 while ( entry ) {
371- cbs . push ( entry . callback ) ;
372- buffer . push ( entry ) ;
383+ buffer [ count ] = entry ;
373384 entry = entry . next ;
385+ count += 1 ;
374386 }
375387
376- // count the one we are adding, as well.
377- // TODO(isaacs) clean this up
388+ doWrite ( stream , state , true , state . length , buffer , '' , holder . finish ) ;
389+
390+ // doWrite is always async, defer these to save a bit of time
391+ // as the hot path ends with doWrite
378392 state . pendingcb ++ ;
379393 state . lastBufferedRequest = null ;
380- doWrite ( stream , state , true , state . length , buffer , '' , function ( err ) {
381- for ( var i = 0 ; i < cbs . length ; i ++ ) {
382- state . pendingcb -- ;
383- cbs [ i ] ( err ) ;
384- }
385- } ) ;
386-
387- // Clear buffer
394+ state . corkedRequestsFree = holder . next ;
395+ holder . next = null ;
388396 } else {
389397 // Slow case, write chunks one-by-one
390398 while ( entry ) {
@@ -407,6 +415,8 @@ function clearBuffer(stream, state) {
407415 if ( entry === null )
408416 state . lastBufferedRequest = null ;
409417 }
418+
419+ state . bufferedRequestCount = 0 ;
410420 state . bufferedRequest = entry ;
411421 state . bufferProcessing = false ;
412422}
@@ -484,3 +494,26 @@ function endWritable(stream, state, cb) {
484494 }
485495 state . ended = true ;
486496}
497+
498+ // It seems a linked list but it is not
499+ // there will be only 2 of these for each stream
500+ function CorkedRequest ( state ) {
501+ this . next = null ;
502+ this . entry = null ;
503+
504+ this . finish = ( err ) => {
505+ var entry = this . entry ;
506+ this . entry = null ;
507+ while ( entry ) {
508+ var cb = entry . callback ;
509+ state . pendingcb -- ;
510+ cb ( err ) ;
511+ entry = entry . next ;
512+ }
513+ if ( state . corkedRequestsFree ) {
514+ state . corkedRequestsFree . next = this ;
515+ } else {
516+ state . corkedRequestsFree = this ;
517+ }
518+ } ;
519+ }
0 commit comments