• 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    // 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