diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 5d2300cf891bca..ba5b9b6986c3a9 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -374,25 +374,6 @@ Readable.prototype.setEncoding = function(enc) { return this; }; -// Don't raise the hwm > 8MB -const MAX_HWM = 0x800000; -function computeNewHighWaterMark(n) { - if (n >= MAX_HWM) { - n = MAX_HWM; - } else { - // Get the next highest power of 2 to prevent increasing hwm excessively in - // tiny amounts - n--; - n |= n >>> 1; - n |= n >>> 2; - n |= n >>> 4; - n |= n >>> 8; - n |= n >>> 16; - n++; - } - return n; -} - // This function is designed to be inlinable, so please take care when making // changes to the function body. function howMuchToRead(n, state) { @@ -425,9 +406,11 @@ Readable.prototype.read = function(n) { const state = this._readableState; const nOrig = n; - // If we're asking for more than the current hwm, then raise the hwm. + // If we're asking for more than the current hwm, then raise the hwm to + // the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts. if (n > state.highWaterMark) - state.highWaterMark = computeNewHighWaterMark(n); + state.highWaterMark = Math.pow(2, Math.ceil(Math.log(n) / Math.log(2))); if (n !== 0) state.emittedReadable = false; diff --git a/test/parallel/test-readable-large-hwm.js b/test/parallel/test-readable-large-hwm.js new file mode 100644 index 00000000000000..d5bf25bc0e61c1 --- /dev/null +++ b/test/parallel/test-readable-large-hwm.js @@ -0,0 +1,27 @@ +'use strict'; +const common = require('../common'); +const { Readable } = require('stream'); + +// Make sure that readable completes +// even when reading larger buffer. +const bufferSize = 10 * 1024 * 1024; +let n = 0; +const r = new Readable({ + read() { + // Try to fill readable buffer piece by piece. + r.push(Buffer.alloc(bufferSize / 10)); + + if (n++ > 10) { + r.push(null); + } + } +}); + +r.on('readable', () => { + while (true) { + const ret = r.read(bufferSize); + if (ret === null) + break; + } +}); +r.on('end', common.mustCall());