@@ -27,9 +27,18 @@ function lazyFs() {
27
27
const kMinPoolSpace = 128 ;
28
28
29
29
let pool ;
30
+ // It can happen that we expect to read a large chunk of data, and reserve
31
+ // a large chunk of the pool accordingly, but the read() call only filled
32
+ // a portion of it. If a concurrently executing read() then uses the same pool,
33
+ // the "reserved" portion cannot be used, so we allow it to be re-used as a
34
+ // new pool later.
35
+ const poolFragments = [ ] ;
30
36
31
37
function allocNewPool ( poolSize ) {
32
- pool = Buffer . allocUnsafe ( poolSize ) ;
38
+ if ( poolFragments . length > 0 )
39
+ pool = poolFragments . pop ( ) ;
40
+ else
41
+ pool = Buffer . allocUnsafe ( poolSize ) ;
33
42
pool . used = 0 ;
34
43
}
35
44
@@ -156,6 +165,14 @@ ReadStream.prototype._read = function(n) {
156
165
this . emit ( 'error' , er ) ;
157
166
} else {
158
167
let b = null ;
168
+ // Now that we know how much data we have actually read, re-wind the
169
+ // 'used' field if we can, and otherwise allow the remainder of our
170
+ // reservation to be used as a new pool later.
171
+ if ( start + toRead === thisPool . used && thisPool === pool )
172
+ thisPool . used += bytesRead - toRead ;
173
+ else if ( toRead - bytesRead > kMinPoolSpace )
174
+ poolFragments . push ( thisPool . slice ( start + bytesRead , start + toRead ) ) ;
175
+
159
176
if ( bytesRead > 0 ) {
160
177
this . bytesRead += bytesRead ;
161
178
b = thisPool . slice ( start , start + bytesRead ) ;
0 commit comments