Skip to content

Commit a3e71a8

Browse files
committed
benchmark: add test double HTTP benchmarker
Refactor benchmark/_http-benchmarkers.js and add a test double HTTP benchmarker for testing. PR-URL: #12121 Refs: #12068 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent c095394 commit a3e71a8

File tree

2 files changed

+106
-54
lines changed

2 files changed

+106
-54
lines changed

benchmark/_http-benchmarkers.js

+99-54
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,119 @@
11
'use strict';
22

33
const child_process = require('child_process');
4+
const path = require('path');
5+
const fs = require('fs');
46

57
// The port used by servers and wrk
68
exports.PORT = process.env.PORT || 12346;
79

8-
function AutocannonBenchmarker() {
9-
this.name = 'autocannon';
10-
this.autocannon_exe = process.platform === 'win32' ?
11-
'autocannon.cmd' :
12-
'autocannon';
13-
const result = child_process.spawnSync(this.autocannon_exe, ['-h']);
14-
this.present = !(result.error && result.error.code === 'ENOENT');
15-
}
10+
class AutocannonBenchmarker {
11+
constructor() {
12+
this.name = 'autocannon';
13+
this.executable = process.platform === 'win32' ?
14+
'autocannon.cmd' :
15+
'autocannon';
16+
const result = child_process.spawnSync(this.executable, ['-h']);
17+
this.present = !(result.error && result.error.code === 'ENOENT');
18+
}
1619

17-
AutocannonBenchmarker.prototype.create = function(options) {
18-
const args = [
19-
'-d', options.duration,
20-
'-c', options.connections,
21-
'-j',
22-
'-n',
23-
`http://127.0.0.1:${options.port}${options.path}`
24-
];
25-
const child = child_process.spawn(this.autocannon_exe, args);
26-
return child;
27-
};
20+
create(options) {
21+
const args = [
22+
'-d', options.duration,
23+
'-c', options.connections,
24+
'-j',
25+
'-n',
26+
`http://127.0.0.1:${options.port}${options.path}`
27+
];
28+
const child = child_process.spawn(this.executable, args);
29+
return child;
30+
}
2831

29-
AutocannonBenchmarker.prototype.processResults = function(output) {
30-
let result;
31-
try {
32-
result = JSON.parse(output);
33-
} catch (err) {
34-
// Do nothing, let next line handle this
32+
processResults(output) {
33+
let result;
34+
try {
35+
result = JSON.parse(output);
36+
} catch (err) {
37+
return undefined;
38+
}
39+
if (!result || !result.requests || !result.requests.average) {
40+
return undefined;
41+
} else {
42+
return result.requests.average;
43+
}
3544
}
36-
if (!result || !result.requests || !result.requests.average) {
37-
return undefined;
38-
} else {
39-
return result.requests.average;
45+
}
46+
47+
class WrkBenchmarker {
48+
constructor() {
49+
this.name = 'wrk';
50+
this.executable = 'wrk';
51+
const result = child_process.spawnSync(this.executable, ['-h']);
52+
this.present = !(result.error && result.error.code === 'ENOENT');
53+
}
54+
55+
create(options) {
56+
const args = [
57+
'-d', options.duration,
58+
'-c', options.connections,
59+
'-t', 8,
60+
`http://127.0.0.1:${options.port}${options.path}`
61+
];
62+
const child = child_process.spawn(this.executable, args);
63+
return child;
4064
}
41-
};
4265

43-
function WrkBenchmarker() {
44-
this.name = 'wrk';
45-
this.regexp = /Requests\/sec:[ \t]+([0-9.]+)/;
46-
const result = child_process.spawnSync('wrk', ['-h']);
47-
this.present = !(result.error && result.error.code === 'ENOENT');
66+
processResults(output) {
67+
const throughputRe = /Requests\/sec:[ \t]+([0-9.]+)/;
68+
const match = output.match(throughputRe);
69+
const throughput = match && +match[1];
70+
if (!isFinite(throughput)) {
71+
return undefined;
72+
} else {
73+
return throughput;
74+
}
75+
}
4876
}
4977

50-
WrkBenchmarker.prototype.create = function(options) {
51-
const args = [
52-
'-d', options.duration,
53-
'-c', options.connections,
54-
'-t', 8,
55-
`http://127.0.0.1:${options.port}${options.path}`
56-
];
57-
const child = child_process.spawn('wrk', args);
58-
return child;
59-
};
78+
/**
79+
* Simple, single-threaded benchmarker for testing if the benchmark
80+
* works
81+
*/
82+
class TestDoubleBenchmarker {
83+
constructor() {
84+
this.name = 'test-double';
85+
this.executable = path.resolve(__dirname, '_test-double-benchmarker.js');
86+
this.present = fs.existsSync(this.executable);
87+
}
88+
89+
create(options) {
90+
const child = child_process.fork(this.executable, {
91+
silent: true,
92+
env: {
93+
duration: options.duration,
94+
connections: options.connections,
95+
path: `http://127.0.0.1:${options.port}${options.path}`
96+
}
97+
});
98+
return child;
99+
}
60100

61-
WrkBenchmarker.prototype.processResults = function(output) {
62-
const match = output.match(this.regexp);
63-
const result = match && +match[1];
64-
if (!isFinite(result)) {
65-
return undefined;
66-
} else {
67-
return result;
101+
processResults(output) {
102+
let result;
103+
try {
104+
result = JSON.parse(output);
105+
} catch (err) {
106+
return undefined;
107+
}
108+
return result.throughput;
68109
}
69-
};
110+
}
70111

71-
const http_benchmarkers = [new WrkBenchmarker(), new AutocannonBenchmarker()];
112+
const http_benchmarkers = [
113+
new WrkBenchmarker(),
114+
new AutocannonBenchmarker(),
115+
new TestDoubleBenchmarker()
116+
];
72117

73118
const benchmarkers = {};
74119

benchmark/_test-double-benchmarker.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
3+
const http = require('http');
4+
5+
http.get(process.env.path, function() {
6+
console.log(JSON.stringify({throughput: 1}));
7+
});

0 commit comments

Comments
 (0)