http2: making sending to the socket more efficient

PR-URL: https://github.com/nodejs/node/pull/15693
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
This commit is contained in:
James M Snell 2017-09-29 16:00:51 -07:00
parent 8691d8bc85
commit 7092a6ca93
2 changed files with 58 additions and 19 deletions

View File

@ -6,17 +6,27 @@ const PORT = common.PORT;
const bench = common.createBenchmark(main, { const bench = common.createBenchmark(main, {
streams: [100, 200, 1000], streams: [100, 200, 1000],
length: [64 * 1024, 128 * 1024, 256 * 1024, 1024 * 1024], length: [64 * 1024, 128 * 1024, 256 * 1024, 1024 * 1024],
size: [100000]
}, { flags: ['--no-warnings'] }); }, { flags: ['--no-warnings'] });
function main(conf) { function main(conf) {
const m = +conf.streams; const m = +conf.streams;
const l = +conf.length; const l = +conf.length;
const s = +conf.size;
const http2 = require('http2'); const http2 = require('http2');
const server = http2.createServer(); const server = http2.createServer();
server.on('stream', (stream) => { server.on('stream', (stream) => {
stream.respond(); stream.respond();
stream.write('ü'.repeat(l)); let written = 0;
stream.end(); function write() {
stream.write('ü'.repeat(s));
written += s;
if (written < l)
setImmediate(write);
else
stream.end();
}
write();
}); });
server.listen(PORT, () => { server.listen(PORT, () => {
bench.http({ bench.http({

View File

@ -478,24 +478,53 @@ inline void Nghttp2Session::SendPendingData() {
// will not be usable. // will not be usable.
if (IsDestroying()) if (IsDestroying())
return; return;
const uint8_t* data;
ssize_t len = 0; uv_buf_t dest;
size_t ncopy = 0; AllocateSend(SEND_BUFFER_RECOMMENDED_SIZE, &dest);
uv_buf_t buf; size_t destLength = 0; // amount of data stored in dest
AllocateSend(SEND_BUFFER_RECOMMENDED_SIZE, &buf); size_t destRemaining = dest.len; // amount space remaining in dest
while (nghttp2_session_want_write(session_)) { size_t destOffset = 0; // current write offset of dest
len = nghttp2_session_mem_send(session_, &data);
CHECK_GE(len, 0); // If this is less than zero, we're out of memory const uint8_t* src; // pointer to the serialized data
// While len is greater than 0, send a chunk ssize_t srcLength = 0; // length of serialized data chunk
while (len > 0) {
ncopy = len; // While srcLength is greater than zero
if (ncopy > buf.len) while ((srcLength = nghttp2_session_mem_send(session_, &src)) > 0) {
ncopy = buf.len; DEBUG_HTTP2("Nghttp2Session %s: nghttp2 has %d bytes to send\n",
memcpy(buf.base, data, ncopy); TypeName(), srcLength);
Send(&buf, ncopy); size_t srcRemaining = srcLength;
len -= ncopy; size_t srcOffset = 0;
CHECK_GE(len, 0); // This should never be less than zero
// The amount of data we have to copy is greater than the space
// remaining. Copy what we can into the remaining space, send it,
// the proceed with the rest.
while (srcRemaining > destRemaining) {
DEBUG_HTTP2("Nghttp2Session %s: pushing %d bytes to the socket\n",
TypeName(), destRemaining);
memcpy(dest.base + destOffset, src + srcOffset, destRemaining);
destLength += destRemaining;
Send(&dest, destLength);
destOffset = 0;
destLength = 0;
srcRemaining -= destRemaining;
srcOffset += destRemaining;
destRemaining = dest.len;
} }
if (srcRemaining > 0) {
memcpy(dest.base + destOffset, src + srcOffset, srcRemaining);
destLength += srcRemaining;
destOffset += srcRemaining;
destRemaining -= srcRemaining;
srcRemaining = 0;
srcOffset = 0;
}
}
if (destLength > 0) {
DEBUG_HTTP2("Nghttp2Session %s: pushing %d bytes to the socket\n",
TypeName(), destLength);
Send(&dest, destLength);
} }
} }