Skip to content

Commit d483ca3

Browse files
jasnelladdaleax
authored andcommitted
http2: making sending to the socket more efficient
PR-URL: nodejs/node#15693 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
1 parent df1dc28 commit d483ca3

2 files changed

Lines changed: 58 additions & 19 deletions

File tree

benchmark/http2/write.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,27 @@ const PORT = common.PORT;
66
const bench = common.createBenchmark(main, {
77
streams: [100, 200, 1000],
88
length: [64 * 1024, 128 * 1024, 256 * 1024, 1024 * 1024],
9+
size: [100000]
910
}, { flags: ['--no-warnings'] });
1011

1112
function main(conf) {
1213
const m = +conf.streams;
1314
const l = +conf.length;
15+
const s = +conf.size;
1416
const http2 = require('http2');
1517
const server = http2.createServer();
1618
server.on('stream', (stream) => {
1719
stream.respond();
18-
stream.write('ü'.repeat(l));
19-
stream.end();
20+
let written = 0;
21+
function write() {
22+
stream.write('ü'.repeat(s));
23+
written += s;
24+
if (written < l)
25+
setImmediate(write);
26+
else
27+
stream.end();
28+
}
29+
write();
2030
});
2131
server.listen(PORT, () => {
2232
bench.http({

src/node_http2_core-inl.h

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -481,25 +481,54 @@ inline void Nghttp2Session::SendPendingData() {
481481
// will not be usable.
482482
if (IsDestroying())
483483
return;
484-
const uint8_t* data;
485-
ssize_t len = 0;
486-
size_t ncopy = 0;
487-
uv_buf_t buf;
488-
AllocateSend(SEND_BUFFER_RECOMMENDED_SIZE, &buf);
489-
while (nghttp2_session_want_write(session_)) {
490-
len = nghttp2_session_mem_send(session_, &data);
491-
CHECK_GE(len, 0); // If this is less than zero, we're out of memory
492-
// While len is greater than 0, send a chunk
493-
while (len > 0) {
494-
ncopy = len;
495-
if (ncopy > buf.len)
496-
ncopy = buf.len;
497-
memcpy(buf.base, data, ncopy);
498-
Send(&buf, ncopy);
499-
len -= ncopy;
500-
CHECK_GE(len, 0); // This should never be less than zero
484+
485+
uv_buf_t dest;
486+
AllocateSend(SEND_BUFFER_RECOMMENDED_SIZE, &dest);
487+
size_t destLength = 0; // amount of data stored in dest
488+
size_t destRemaining = dest.len; // amount space remaining in dest
489+
size_t destOffset = 0; // current write offset of dest
490+
491+
const uint8_t* src; // pointer to the serialized data
492+
ssize_t srcLength = 0; // length of serialized data chunk
493+
494+
// While srcLength is greater than zero
495+
while ((srcLength = nghttp2_session_mem_send(session_, &src)) > 0) {
496+
DEBUG_HTTP2("Nghttp2Session %s: nghttp2 has %d bytes to send\n",
497+
TypeName(), srcLength);
498+
size_t srcRemaining = srcLength;
499+
size_t srcOffset = 0;
500+
501+
// The amount of data we have to copy is greater than the space
502+
// remaining. Copy what we can into the remaining space, send it,
503+
// the proceed with the rest.
504+
while (srcRemaining > destRemaining) {
505+
DEBUG_HTTP2("Nghttp2Session %s: pushing %d bytes to the socket\n",
506+
TypeName(), destRemaining);
507+
memcpy(dest.base + destOffset, src + srcOffset, destRemaining);
508+
destLength += destRemaining;
509+
Send(&dest, destLength);
510+
destOffset = 0;
511+
destLength = 0;
512+
srcRemaining -= destRemaining;
513+
srcOffset += destRemaining;
514+
destRemaining = dest.len;
515+
}
516+
517+
if (srcRemaining > 0) {
518+
memcpy(dest.base + destOffset, src + srcOffset, srcRemaining);
519+
destLength += srcRemaining;
520+
destOffset += srcRemaining;
521+
destRemaining -= srcRemaining;
522+
srcRemaining = 0;
523+
srcOffset = 0;
501524
}
502525
}
526+
527+
if (destLength > 0) {
528+
DEBUG_HTTP2("Nghttp2Session %s: pushing %d bytes to the socket\n",
529+
TypeName(), destLength);
530+
Send(&dest, destLength);
531+
}
503532
}
504533

505534
// Initialize the Nghttp2Session handle by creating and

0 commit comments

Comments
 (0)