@@ -108,6 +108,14 @@ function WritableState(options, stream) {
108
108
109
109
// True if the error was already emitted and should not be thrown again
110
110
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 ) ;
111
119
}
112
120
113
121
WritableState . prototype . getBuffer = function writableStateGetBuffer ( ) {
@@ -274,6 +282,7 @@ function writeOrBuffer(stream, state, chunk, encoding, cb) {
274
282
} else {
275
283
state . bufferedRequest = state . lastBufferedRequest ;
276
284
}
285
+ state . bufferedRequestCount += 1 ;
277
286
} else {
278
287
doWrite ( stream , state , false , len , chunk , encoding , cb ) ;
279
288
}
@@ -357,34 +366,33 @@ function onwriteDrain(stream, state) {
357
366
}
358
367
}
359
368
360
-
361
369
// if there's something in the buffer waiting, then process it
362
370
function clearBuffer ( stream , state ) {
363
371
state . bufferProcessing = true ;
364
372
var entry = state . bufferedRequest ;
365
373
366
374
if ( stream . _writev && entry && entry . next ) {
367
375
// 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 ;
370
382
while ( entry ) {
371
- cbs . push ( entry . callback ) ;
372
- buffer . push ( entry ) ;
383
+ buffer [ count ] = entry ;
373
384
entry = entry . next ;
385
+ count += 1 ;
374
386
}
375
387
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
378
392
state . pendingcb ++ ;
379
393
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 ;
388
396
} else {
389
397
// Slow case, write chunks one-by-one
390
398
while ( entry ) {
@@ -407,6 +415,8 @@ function clearBuffer(stream, state) {
407
415
if ( entry === null )
408
416
state . lastBufferedRequest = null ;
409
417
}
418
+
419
+ state . bufferedRequestCount = 0 ;
410
420
state . bufferedRequest = entry ;
411
421
state . bufferProcessing = false ;
412
422
}
@@ -485,3 +495,26 @@ function endWritable(stream, state, cb) {
485
495
state . ended = true ;
486
496
stream . writable = false ;
487
497
}
498
+
499
+ // It seems a linked list but it is not
500
+ // there will be only 2 of these for each stream
501
+ function CorkedRequest ( state ) {
502
+ this . next = null ;
503
+ this . entry = null ;
504
+
505
+ this . finish = ( err ) => {
506
+ var entry = this . entry ;
507
+ this . entry = null ;
508
+ while ( entry ) {
509
+ var cb = entry . callback ;
510
+ state . pendingcb -- ;
511
+ cb ( err ) ;
512
+ entry = entry . next ;
513
+ }
514
+ if ( state . corkedRequestsFree ) {
515
+ state . corkedRequestsFree . next = this ;
516
+ } else {
517
+ state . corkedRequestsFree = this ;
518
+ }
519
+ } ;
520
+ }
0 commit comments