• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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