Skip to content

Commit

Permalink
http2: shrink memory to match read data
Browse files Browse the repository at this point in the history
Perform a shrinking `Realloc()` so that less data is
used for HTTP2 reads.

PR-URL: nodejs#26201
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
addaleax committed Feb 21, 2019
1 parent e51da1f commit 83e1b97
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 20 deletions.
35 changes: 16 additions & 19 deletions src/node_http2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1774,17 +1774,8 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
Http2Scope h2scope(this);
CHECK_NOT_NULL(stream_);
Debug(this, "receiving %d bytes", nread);
IncrementCurrentSessionMemory(buf.len);
CHECK(stream_buf_ab_.IsEmpty());

OnScopeLeave on_scope_leave([&]() {
// Once finished handling this write, reset the stream buffer.
// The memory has either been free()d or was handed over to V8.
DecrementCurrentSessionMemory(buf.len);
stream_buf_ab_ = Local<ArrayBuffer>();
stream_buf_ = uv_buf_init(nullptr, 0);
});

// Only pass data on if nread > 0
if (nread <= 0) {
free(buf.base);
Expand All @@ -1794,29 +1785,35 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
return;
}

// Shrink to the actual amount of used data.
char* base = Realloc(buf.base, nread);

IncrementCurrentSessionMemory(nread);
OnScopeLeave on_scope_leave([&]() {
// Once finished handling this write, reset the stream buffer.
// The memory has either been free()d or was handed over to V8.
DecrementCurrentSessionMemory(nread);
stream_buf_ab_ = Local<ArrayBuffer>();
stream_buf_ = uv_buf_init(nullptr, 0);
});

// Make sure that there was no read previously active.
CHECK_NULL(stream_buf_.base);
CHECK_EQ(stream_buf_.len, 0);

// Remember the current buffer, so that OnDataChunkReceived knows the
// offset of a DATA frame's data into the socket read buffer.
stream_buf_ = uv_buf_init(buf.base, nread);

// Verify that currently: There is memory allocated into which
// the data has been read, and that memory buffer is at least as large
// as the amount of data we have read, but we have not yet made an
// ArrayBuffer out of it.
CHECK_LE(static_cast<size_t>(nread), stream_buf_.len);
stream_buf_ = uv_buf_init(base, nread);

Isolate* isolate = env()->isolate();

// Create an array buffer for the read data. DATA frames will be emitted
// as slices of this array buffer to avoid having to copy memory.
stream_buf_ab_ =
ArrayBuffer::New(isolate,
buf.base,
nread,
ArrayBufferCreationMode::kInternalized);
base,
nread,
ArrayBufferCreationMode::kInternalized);

statistics_.data_received += nread;
ssize_t ret = Write(&stream_buf_, 1);
Expand Down
2 changes: 1 addition & 1 deletion test/sequential/test-http2-max-session-memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const http2 = require('http2');

// Test that maxSessionMemory Caps work

const largeBuffer = Buffer.alloc(1e6);
const largeBuffer = Buffer.alloc(2e6);

const server = http2.createServer({ maxSessionMemory: 1 });

Expand Down

0 comments on commit 83e1b97

Please sign in to comment.