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 let chunk; 43 switch (type) { 44 case 'buf': 45 chunk = Buffer.alloc(len, 'x'); 46 break; 47 case 'utf': 48 chunk = 'ü'.repeat(len / 2); 49 break; 50 case 'asc': 51 chunk = 'x'.repeat(len); 52 break; 53 default: 54 throw new Error(`invalid type: ${type}`); 55 } 56 57 clientHandle.readStart(); 58 59 while (clientHandle.writeQueueSize === 0) 60 write(); 61 62 function write() { 63 const writeReq = new WriteWrap(); 64 writeReq.async = false; 65 writeReq.oncomplete = afterWrite; 66 let err; 67 switch (type) { 68 case 'buf': 69 err = clientHandle.writeBuffer(writeReq, chunk); 70 break; 71 case 'utf': 72 err = clientHandle.writeUtf8String(writeReq, chunk); 73 break; 74 case 'asc': 75 err = clientHandle.writeAsciiString(writeReq, chunk); 76 break; 77 } 78 79 if (err) { 80 fail(err, 'write'); 81 } else if (!writeReq.async) { 82 process.nextTick(() => { 83 afterWrite(0, clientHandle); 84 }); 85 } 86 } 87 88 function afterWrite(status, handle) { 89 if (status) 90 fail(status, 'write'); 91 92 while (clientHandle.writeQueueSize === 0) 93 write(); 94 } 95 }; 96 97 client(dur); 98 99 function fail(err, syscall) { 100 throw util._errnoException(err, syscall); 101 } 102 103 function client(dur) { 104 const clientHandle = new TCP(TCPConstants.SOCKET); 105 const connectReq = new TCPConnectWrap(); 106 const err = clientHandle.connect(connectReq, '127.0.0.1', PORT); 107 108 if (err) 109 fail(err, 'connect'); 110 111 connectReq.oncomplete = function() { 112 let bytes = 0; 113 clientHandle.onread = function(buffer) { 114 // We're not expecting to ever get an EOF from the client. 115 // Just lots of data forever. 116 if (!buffer) 117 fail('read'); 118 119 // Don't slice the buffer. The point of this is to isolate, not 120 // simulate real traffic. 121 bytes += buffer.byteLength; 122 }; 123 124 clientHandle.readStart(); 125 126 // The meat of the benchmark is right here: 127 bench.start(); 128 129 setTimeout(() => { 130 // report in Gb/sec 131 bench.end((bytes * 8) / (1024 * 1024 * 1024)); 132 process.exit(0); 133 }, dur * 1000); 134 }; 135 } 136} 137