Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Option to configure highWaterMark of HTTP response #30107

Closed
trentmwillis opened this issue Oct 24, 2019 · 5 comments · Fixed by #30135
Closed

Feature Request: Option to configure highWaterMark of HTTP response #30107

trentmwillis opened this issue Oct 24, 2019 · 5 comments · Fixed by #30135
Labels
feature request Issues that request new features to be added to Node.js. http Issues or PRs related to the http subsystem. stream Issues and PRs related to the stream subsystem.

Comments

@trentmwillis
Copy link

Is your feature request related to a problem? Please describe.

We have a Node service that loads a bunch of data over an HTTP connection using Server-Sent Events. We noticed, when comparing to implementations in other languages, that the data we receive winds up being in many more "chunks" in Node which leads to some performance issues.

After some digging, it seems that the issue is that http.ServerResponse received when using http.request() uses the default highWaterMark value of 16kb inherited from the default ReadableStream class. This is much smaller than some of the messages we're processing which we believe is the cause of the perf issues since we must reconstruct the messages before parsing them fully.

Describe the solution you'd like

Ideally, an option to configure the highWaterMark size of a response when calling http.request.

It might be that there is a way to do what we need here, but I was not able to find it if so. So I'm open to feedback on that front.

Describe alternatives you've considered

Some way to override the default highWaterMark size of a stream (e.g., a CLI option), but that feels more expansive than needed.

Thanks in advance for your help/consideration 😃

@trentmwillis trentmwillis changed the title Option to configure highWaterMark of HTTP response Feature Request: Option to configure highWaterMark of HTTP response Oct 24, 2019
@cjihrig
Copy link
Contributor

cjihrig commented Oct 25, 2019

It looks like passing readableHighWaterMark to http.request() already properly sets the highWaterMark on the stream's underlying socket. From there, the following patch propagates it to the IncomingMessage instance. Node's test suite passes for me with this change as well.

diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js
index ad3699cc44..4f9c501377 100644
--- a/lib/_http_incoming.js
+++ b/lib/_http_incoming.js
@@ -37,7 +37,9 @@ function readStop(socket) {
 
 /* Abstract base class for ServerRequest and ClientResponse. */
 function IncomingMessage(socket) {
-  Stream.Readable.call(this);
+  let streamOptions;
+
+  if (socket) {
+    streamOptions = {
+      highWaterMark: socket.readableHighWaterMark
+    };
+  }
+
+  Stream.Readable.call(this, streamOptions);
 
   this._readableState.readingMore = true;

@trentmwillis
Copy link
Author

@cjihrig thanks for looking into this! To clarify, does that mean the patch above will need to land for this to work as desired? The end result being you'd use it like so:

http.request('https://example.com', { readableHighWaterMark: 1000000 }, (response) => {
  console.log(response.readableHighWaterMark); // 1000000
});

@ZYSzys ZYSzys added feature request Issues that request new features to be added to Node.js. http Issues or PRs related to the http subsystem. stream Issues and PRs related to the stream subsystem. labels Oct 26, 2019
@cjihrig
Copy link
Contributor

cjihrig commented Oct 26, 2019

So, thinking about this a bit more, I don't think we'd want to officially support passing readableHighWaterMark directly in http.request() and https.request() because it wouldn't work properly with agents that reuse existing sockets (AFAIK, changing the highWaterMark after stream construction is not supported). I think the better approach is to use the createConnection() option to http.request() or a custom agent to create sockets with the desired high water mark.

Unfortunately, I think we'd still need something like the patch above to set the highWaterMark of the IncomingMessage to match that of the socket, and that might end up as a semver-major change to the IncomingMessage class.

I've opened #30135 as a possible solution.

@trentmwillis
Copy link
Author

Thanks for getting this implemented so quickly! I took a look at the PR and your solution makes sense and works for our use case 💯

targos pushed a commit that referenced this issue Nov 5, 2019
This commit causes http.IncomingMessage instances to set their
readableHighWaterMark value the same value used in the underlying
socket.

PR-URL: #30135
Fixes: #30107
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
MylesBorins pushed a commit that referenced this issue Jan 12, 2020
This commit causes http.IncomingMessage instances to set their
readableHighWaterMark value the same value used in the underlying
socket.

PR-URL: #30135
Fixes: #30107
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
BethGriggs pushed a commit that referenced this issue Feb 6, 2020
This commit causes http.IncomingMessage instances to set their
readableHighWaterMark value the same value used in the underlying
socket.

PR-URL: #30135
Fixes: #30107
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
@0807Jpatel
Copy link

Is there a way to do this on server side? http.createServer because hwm of response stream is larger than we would like it to be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issues that request new features to be added to Node.js. http Issues or PRs related to the http subsystem. stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants