| // In this benchmark, we connect a client to the server, and write |
| // as many bytes as we can in the specified time (default = 10s) |
| 'use strict'; |
| |
| const common = require('../common.js'); |
| const util = require('util'); |
| |
| // If there are dur=N and len=N args, then |
| // run the function with those settings. |
| // If not, then queue up a bunch of child processes. |
| const bench = common.createBenchmark(main, { |
| len: [102400, 1024 * 1024 * 16], |
| type: ['utf', 'asc', 'buf'], |
| dur: [5] |
| }, { |
| flags: [ '--expose-internals', '--no-warnings' ] |
| }); |
| |
| function main({ dur, len, type }) { |
| const { |
| TCP, |
| TCPConnectWrap, |
| constants: TCPConstants |
| } = common.binding('tcp_wrap'); |
| const { WriteWrap } = common.binding('stream_wrap'); |
| const PORT = common.PORT; |
| |
| const serverHandle = new TCP(TCPConstants.SERVER); |
| let err = serverHandle.bind('127.0.0.1', PORT); |
| if (err) |
| fail(err, 'bind'); |
| |
| err = serverHandle.listen(511); |
| if (err) |
| fail(err, 'listen'); |
| |
| serverHandle.onconnection = function(err, clientHandle) { |
| if (err) |
| fail(err, 'connect'); |
| |
| let chunk; |
| switch (type) { |
| case 'buf': |
| chunk = Buffer.alloc(len, 'x'); |
| break; |
| case 'utf': |
| chunk = 'ΓΌ'.repeat(len / 2); |
| break; |
| case 'asc': |
| chunk = 'x'.repeat(len); |
| break; |
| default: |
| throw new Error(`invalid type: ${type}`); |
| } |
| |
| clientHandle.readStart(); |
| |
| while (clientHandle.writeQueueSize === 0) |
| write(); |
| |
| function write() { |
| const writeReq = new WriteWrap(); |
| writeReq.async = false; |
| writeReq.oncomplete = afterWrite; |
| let err; |
| switch (type) { |
| case 'buf': |
| err = clientHandle.writeBuffer(writeReq, chunk); |
| break; |
| case 'utf': |
| err = clientHandle.writeUtf8String(writeReq, chunk); |
| break; |
| case 'asc': |
| err = clientHandle.writeAsciiString(writeReq, chunk); |
| break; |
| } |
| |
| if (err) { |
| fail(err, 'write'); |
| } else if (!writeReq.async) { |
| process.nextTick(() => { |
| afterWrite(0, clientHandle); |
| }); |
| } |
| } |
| |
| function afterWrite(status, handle) { |
| if (status) |
| fail(status, 'write'); |
| |
| while (clientHandle.writeQueueSize === 0) |
| write(); |
| } |
| }; |
| |
| client(dur); |
| |
| function fail(err, syscall) { |
| throw util._errnoException(err, syscall); |
| } |
| |
| function client(dur) { |
| const clientHandle = new TCP(TCPConstants.SOCKET); |
| const connectReq = new TCPConnectWrap(); |
| const err = clientHandle.connect(connectReq, '127.0.0.1', PORT); |
| |
| if (err) |
| fail(err, 'connect'); |
| |
| connectReq.oncomplete = function() { |
| let bytes = 0; |
| clientHandle.onread = function(buffer) { |
| // We're not expecting to ever get an EOF from the client. |
| // Just lots of data forever. |
| if (!buffer) |
| fail('read'); |
| |
| // Don't slice the buffer. The point of this is to isolate, not |
| // simulate real traffic. |
| bytes += buffer.byteLength; |
| }; |
| |
| clientHandle.readStart(); |
| |
| // The meat of the benchmark is right here: |
| bench.start(); |
| |
| setTimeout(() => { |
| // report in Gb/sec |
| bench.end((bytes * 8) / (1024 * 1024 * 1024)); |
| process.exit(0); |
| }, dur * 1000); |
| }; |
| } |
| } |