Skip to content

Commit 05b823d

Browse files
addaleaxMylesBorins
authored andcommitted
http2: remove redundant write indirection
`nghttp2_stream_write_t` was not a necessary redirection layer and came with the cost of one additional allocation per stream write. Also, having both `nghttp2_stream_write` and `nghttp2_stream_write_t` as identifiers did not help with readability. Backport-PR-URL: #18050 Backport-PR-URL: #20456 PR-URL: #17718 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent fc40b7d commit 05b823d

File tree

2 files changed

+19
-57
lines changed

2 files changed

+19
-57
lines changed

src/node_http2.cc

+18-36
Original file line numberDiff line numberDiff line change
@@ -1369,30 +1369,6 @@ inline void Http2Stream::AddChunk(const uint8_t* data, size_t len) {
13691369
data_chunks_.emplace(uv_buf_init(buf, len));
13701370
}
13711371

1372-
// The Http2Stream class is a subclass of StreamBase. The DoWrite method
1373-
// receives outbound chunks of data to send as outbound DATA frames. These
1374-
// are queued in an internal linked list of uv_buf_t structs that are sent
1375-
// when nghttp2 is ready to serialize the data frame.
1376-
int Http2Stream::DoWrite(WriteWrap* req_wrap,
1377-
uv_buf_t* bufs,
1378-
size_t count,
1379-
uv_stream_t* send_handle) {
1380-
CHECK(!this->IsDestroyed());
1381-
session_->SetChunksSinceLastWrite();
1382-
1383-
nghttp2_stream_write_t* req = new nghttp2_stream_write_t;
1384-
req->data = req_wrap;
1385-
1386-
auto AfterWrite = [](nghttp2_stream_write_t* req, int status) {
1387-
WriteWrap* wrap = static_cast<WriteWrap*>(req->data);
1388-
wrap->Done(status);
1389-
delete req;
1390-
};
1391-
req_wrap->Dispatched();
1392-
Write(req, bufs, count, AfterWrite);
1393-
return 0;
1394-
}
1395-
13961372

13971373
inline void Http2Stream::Close(int32_t code) {
13981374
CHECK(!this->IsDestroyed());
@@ -1447,7 +1423,7 @@ inline void Http2Stream::Destroy() {
14471423
// we still have qeueued outbound writes.
14481424
while (!stream->queue_.empty()) {
14491425
nghttp2_stream_write* head = stream->queue_.front();
1450-
head->cb(head->req, UV_ECANCELED);
1426+
head->req_wrap->Done(UV_ECANCELED);
14511427
delete head;
14521428
stream->queue_.pop();
14531429
}
@@ -1616,26 +1592,32 @@ inline int Http2Stream::ReadStop() {
16161592
return 0;
16171593
}
16181594

1595+
// The Http2Stream class is a subclass of StreamBase. The DoWrite method
1596+
// receives outbound chunks of data to send as outbound DATA frames. These
1597+
// are queued in an internal linked list of uv_buf_t structs that are sent
1598+
// when nghttp2 is ready to serialize the data frame.
1599+
//
16191600
// Queue the given set of uv_but_t handles for writing to an
1620-
// nghttp2_stream. The callback will be invoked once the chunks
1621-
// of data have been flushed to the underlying nghttp2_session.
1601+
// nghttp2_stream. The WriteWrap's Done callback will be invoked once the
1602+
// chunks of data have been flushed to the underlying nghttp2_session.
16221603
// Note that this does *not* mean that the data has been flushed
16231604
// to the socket yet.
1624-
inline int Http2Stream::Write(nghttp2_stream_write_t* req,
1625-
const uv_buf_t bufs[],
1626-
unsigned int nbufs,
1627-
nghttp2_stream_write_cb cb) {
1605+
inline int Http2Stream::DoWrite(WriteWrap* req_wrap,
1606+
uv_buf_t* bufs,
1607+
size_t nbufs,
1608+
uv_stream_t* send_handle) {
16281609
CHECK(!this->IsDestroyed());
1610+
CHECK_EQ(send_handle, nullptr);
16291611
Http2Scope h2scope(this);
1612+
session_->SetChunksSinceLastWrite();
1613+
req_wrap->Dispatched();
16301614
if (!IsWritable()) {
1631-
if (cb != nullptr)
1632-
cb(req, UV_EOF);
1615+
req_wrap->Done(UV_EOF);
16331616
return 0;
16341617
}
16351618
DEBUG_HTTP2STREAM2(this, "queuing %d buffers to send", id_, nbufs);
16361619
nghttp2_stream_write* item = new nghttp2_stream_write;
1637-
item->cb = cb;
1638-
item->req = req;
1620+
item->req_wrap = req_wrap;
16391621
item->nbufs = nbufs;
16401622
item->bufs.AllocateSufficientStorage(nbufs);
16411623
memcpy(*(item->bufs), bufs, nbufs * sizeof(*bufs));
@@ -1824,7 +1806,7 @@ ssize_t Http2Stream::Provider::Stream::OnRead(nghttp2_session* handle,
18241806
stream->queue_offset_ = 0;
18251807
}
18261808
if (stream->queue_index_ == head->nbufs) {
1827-
head->cb(head->req, 0);
1809+
head->req_wrap->Done(0);
18281810
delete head;
18291811
stream->queue_.pop();
18301812
stream->queue_offset_ = 0;

src/node_http2.h

+1-21
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ void inline debug_vfprintf(const char* format, ...) {
9191

9292
#define MAX_BUFFER_COUNT 16
9393

94-
struct nghttp2_stream_write_t;
95-
9694
enum nghttp2_session_type {
9795
NGHTTP2_SESSION_SERVER,
9896
NGHTTP2_SESSION_CLIENT
@@ -127,15 +125,9 @@ enum nghttp2_stream_options {
127125
STREAM_OPTION_GET_TRAILERS = 0x2,
128126
};
129127

130-
// Callbacks
131-
typedef void (*nghttp2_stream_write_cb)(
132-
nghttp2_stream_write_t* req,
133-
int status);
134-
135128
struct nghttp2_stream_write {
136129
unsigned int nbufs = 0;
137-
nghttp2_stream_write_t* req = nullptr;
138-
nghttp2_stream_write_cb cb = nullptr;
130+
WriteWrap* req_wrap = nullptr;
139131
MaybeStackBuffer<uv_buf_t, MAX_BUFFER_COUNT> bufs;
140132
};
141133

@@ -146,11 +138,6 @@ struct nghttp2_header {
146138
};
147139

148140

149-
struct nghttp2_stream_write_t {
150-
void* data;
151-
int status;
152-
};
153-
154141
// Unlike the HTTP/1 implementation, the HTTP/2 implementation is not limited
155142
// to a fixed number of known supported HTTP methods. These constants, therefore
156143
// are provided strictly as a convenience to users and are exposed via the
@@ -557,13 +544,6 @@ class Http2Stream : public AsyncWrap,
557544

558545
Http2Session* session() { return session_; }
559546

560-
// Queue outbound chunks of data to be sent on this stream
561-
inline int Write(
562-
nghttp2_stream_write_t* req,
563-
const uv_buf_t bufs[],
564-
unsigned int nbufs,
565-
nghttp2_stream_write_cb cb);
566-
567547
inline bool HasDataChunks(bool ignore_eos = false);
568548

569549
inline void AddChunk(const uint8_t* data, size_t len);

0 commit comments

Comments
 (0)