Skip to content
Permalink
Browse files

stream: increase MAX_HWM

MAX_HWM was added in 9208c89 where the highwatermark was changed to
always increase in steps of highest power of 2 to prevent increasing
hwm excessivly in tiny amounts.

Why a limit was added on the highwatermark is unclear but breaks
existing usage where a larger read size is used. The invariant for
read(n) is that a buffer of size n is always returned. Considering
a maximum ceiling on the buffer size breaks this invariant.

This PR significantly increases the limit to make it less likely to
break the previous invariant and also documents the limit.

Fixes: #29933

PR-URL: #29938
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
ronag authored and BethGriggs committed Oct 20, 2019
1 parent a1b095d commit 77e0318849aa229b24bb5f30d3a919d8e133c226
Showing with 32 additions and 2 deletions.
  1. +2 −0 doc/api/stream.md
  2. +3 −2 lib/_stream_readable.js
  3. +27 −0 test/parallel/test-readable-large-hwm.js
@@ -1010,6 +1010,8 @@ buffer will be returned.
If the `size` argument is not specified, all of the data contained in the
internal buffer will be returned.

The `size` argument must be less than or equal to 1 GB.

The `readable.read()` method should only be called on `Readable` streams
operating in paused mode. In flowing mode, `readable.read()` is called
automatically until the internal buffer is fully drained.
@@ -340,10 +340,11 @@ Readable.prototype.setEncoding = function(enc) {
return this;
};

// Don't raise the hwm > 8MB
const MAX_HWM = 0x800000;
// Don't raise the hwm > 1GB
const MAX_HWM = 0x40000000;
function computeNewHighWaterMark(n) {
if (n >= MAX_HWM) {
// TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE.
n = MAX_HWM;
} else {
// Get the next highest power of 2 to prevent increasing hwm excessively in
@@ -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());

0 comments on commit 77e0318

Please sign in to comment.
You can’t perform that action at this time.