From dfc0ef5d88b03d1ba472287c9908f060893edb41 Mon Sep 17 00:00:00 2001 From: Brian White Date: Thu, 10 Jan 2019 15:52:27 -0500 Subject: [PATCH] net: allow reading data into a static buffer Co-Authored-By: Anna Henningsen PR-URL: https://github.com/nodejs/node/pull/25436 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Ben Noordhuis --- benchmark/net/net-s2c.js | 57 ++++-- doc/api/net.md | 36 ++++ lib/internal/stream_base_commons.js | 31 ++- lib/net.js | 144 ++++++++++---- src/stream_base.cc | 59 +++++- src/stream_base.h | 26 ++- .../parallel/test-net-onread-static-buffer.js | 186 ++++++++++++++++++ 7 files changed, 474 insertions(+), 65 deletions(-) create mode 100644 test/parallel/test-net-onread-static-buffer.js diff --git a/benchmark/net/net-s2c.js b/benchmark/net/net-s2c.js index e3c5c7e5eb41c6..d8c26db9bdb035 100644 --- a/benchmark/net/net-s2c.js +++ b/benchmark/net/net-s2c.js @@ -5,33 +5,68 @@ const common = require('../common.js'); const PORT = common.PORT; const bench = common.createBenchmark(main, { - len: [64, 102400, 1024 * 1024 * 16], + sendchunklen: [256, 32 * 1024, 128 * 1024, 16 * 1024 * 1024], type: ['utf', 'asc', 'buf'], + recvbuflen: [0, 64 * 1024, 1024 * 1024], + recvbufgenfn: ['true', 'false'], dur: [5] }); var chunk; var encoding; +var recvbuf; +var received = 0; + +function main({ dur, sendchunklen, type, recvbuflen, recvbufgenfn }) { + if (isFinite(recvbuflen) && recvbuflen > 0) + recvbuf = Buffer.alloc(recvbuflen); -function main({ dur, len, type }) { switch (type) { case 'buf': - chunk = Buffer.alloc(len, 'x'); + chunk = Buffer.alloc(sendchunklen, 'x'); break; case 'utf': encoding = 'utf8'; - chunk = 'ü'.repeat(len / 2); + chunk = 'ü'.repeat(sendchunklen / 2); break; case 'asc': encoding = 'ascii'; - chunk = 'x'.repeat(len); + chunk = 'x'.repeat(sendchunklen); break; default: throw new Error(`invalid type: ${type}`); } const reader = new Reader(); - const writer = new Writer(); + var writer; + var socketOpts; + if (recvbuf === undefined) { + writer = new Writer(); + socketOpts = { port: PORT }; + } else { + let buffer = recvbuf; + if (recvbufgenfn === 'true') { + let bufidx = -1; + const bufpool = [ + recvbuf, + Buffer.from(recvbuf), + Buffer.from(recvbuf), + ]; + buffer = () => { + bufidx = (bufidx + 1) % bufpool.length; + return bufpool[bufidx]; + }; + } + socketOpts = { + port: PORT, + onread: { + buffer, + callback: function(nread, buf) { + received += nread; + } + } + }; + } // The actual benchmark. const server = net.createServer((socket) => { @@ -39,14 +74,15 @@ function main({ dur, len, type }) { }); server.listen(PORT, () => { - const socket = net.connect(PORT); + const socket = net.connect(socketOpts); socket.on('connect', () => { bench.start(); - socket.pipe(writer); + if (recvbuf === undefined) + socket.pipe(writer); setTimeout(() => { - const bytes = writer.received; + const bytes = received; const gbits = (bytes * 8) / (1024 * 1024 * 1024); bench.end(gbits); process.exit(0); @@ -58,12 +94,11 @@ function main({ dur, len, type }) { const net = require('net'); function Writer() { - this.received = 0; this.writable = true; } Writer.prototype.write = function(chunk, encoding, cb) { - this.received += chunk.length; + received += chunk.length; if (typeof encoding === 'function') encoding(); diff --git a/doc/api/net.md b/doc/api/net.md index 396cad36ab18dd..a396edf31a97bc 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -593,6 +593,9 @@ for the [`'connect'`][] event **once**.