1// In this benchmark, we connect a client to the server, and write 2// as many bytes as we can in the specified time (default = 10s) 3'use strict'; 4 5const common = require('../common.js'); 6const util = require('util'); 7 8// If there are --dur=N and --len=N args, then 9// run the function with those settings. 10// if not, then queue up a bunch of child processes. 11const bench = common.createBenchmark(main, { 12 len: [102400, 1024 * 1024 * 16], 13 type: ['utf', 'asc', 'buf'], 14 dur: [5], 15}, { 16 test: { len: 1024 }, 17 flags: [ '--expose-internals', '--no-warnings' ], 18}); 19 20function main({ dur, len, type }) { 21 const { 22 TCP, 23 TCPConnectWrap, 24 constants: TCPConstants, 25 } = common.binding('tcp_wrap'); 26 const { WriteWrap } = common.binding('stream_wrap'); 27 const PORT = common.PORT; 28 29 const serverHandle = new TCP(TCPConstants.SERVER); 30 let err = serverHandle.bind('127.0.0.1', PORT); 31 if (err) 32 fail(err, 'bind'); 33 34 err = serverHandle.listen(511); 35 if (err) 36 fail(err, 'listen'); 37 38 serverHandle.onconnection = function(err, clientHandle) { 39 if (err) 40 fail(err, 'connect'); 41 42 // The meat of the benchmark is right here: 43 bench.start(); 44 let bytes = 0; 45 46 setTimeout(() => { 47 // report in Gb/sec 48 bench.end((bytes * 8) / (1024 * 1024 * 1024)); 49 process.exit(0); 50 }, dur * 1000); 51 52 clientHandle.onread = function(buffer) { 53 // We're not expecting to ever get an EOF from the client. 54 // Just lots of data forever. 55 if (!buffer) 56 fail('read'); 57 58 // Don't slice the buffer. The point of this is to isolate, not 59 // simulate real traffic. 60 bytes += buffer.byteLength; 61 }; 62 63 clientHandle.readStart(); 64 }; 65 66 client(type, len); 67 68 function fail(err, syscall) { 69 throw util._errnoException(err, syscall); 70 } 71 72 function client(type, len) { 73 let chunk; 74 switch (type) { 75 case 'buf': 76 chunk = Buffer.alloc(len, 'x'); 77 break; 78 case 'utf': 79 chunk = 'ü'.repeat(len / 2); 80 break; 81 case 'asc': 82 chunk = 'x'.repeat(len); 83 break; 84 default: 85 throw new Error(`invalid type: ${type}`); 86 } 87 88 const clientHandle = new TCP(TCPConstants.SOCKET); 89 const connectReq = new TCPConnectWrap(); 90 const err = clientHandle.connect(connectReq, '127.0.0.1', PORT); 91 92 if (err) 93 fail(err, 'connect'); 94 95 clientHandle.readStart(); 96 97 connectReq.oncomplete = function(err) { 98 if (err) 99 fail(err, 'connect'); 100 101 while (clientHandle.writeQueueSize === 0) 102 write(); 103 }; 104 105 function write() { 106 const writeReq = new WriteWrap(); 107 writeReq.oncomplete = afterWrite; 108 let err; 109 switch (type) { 110 case 'buf': 111 err = clientHandle.writeBuffer(writeReq, chunk); 112 break; 113 case 'utf': 114 err = clientHandle.writeUtf8String(writeReq, chunk); 115 break; 116 case 'asc': 117 err = clientHandle.writeAsciiString(writeReq, chunk); 118 break; 119 } 120 121 if (err) 122 fail(err, 'write'); 123 } 124 125 function afterWrite(err, handle) { 126 if (err) 127 fail(err, 'write'); 128 129 while (clientHandle.writeQueueSize === 0) 130 write(); 131 } 132 } 133} 134