Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

benchmark, test: test the HTTP benchmark with a dummy benchmarker #12121

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
benchmark: add dummy HTTP benchmarker
Refactor benchmark/_http-benchmarkers.js and add a dummy
HTTP benchmarker for testing.
  • Loading branch information
joyeecheung committed Apr 8, 2017
commit ce42c0365bcdb2d31d5fcf1d665beead50c2d3ba
7 changes: 7 additions & 0 deletions benchmark/_dummy-benchmarker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not intending to be pedantic... but can we use _noop-benchmarker (noop for non-operational) instead of _dummy-....

Copy link
Member

@Trott Trott Mar 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like noop because noop means "no operator". A noop should do nothing whatsoever. But that's not the case here.

In this case, this is a test double, so _test-double-benchmarker maybe? Sometimes people call certain types of test doubles mocks and other types stubs, so mock-benchmarker or stub-benchmarker might also be appropriate. (I stick to test double so that I don't have to worry about whether or not something is a mock or a stub.)

Copy link
Member

@Trott Trott Mar 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I'm fine with whatever name because this is an internal thing and we can always change it later. So if @jasnell or someone else disagrees with my suggestions,
¯\(ツ)/¯.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's not really a noop since it does connects to the server (a real noop-benchmarker would just skip the http.get call and write to stdout straight away). I think _test-double-benchmarker is better :D


const http = require('http');

http.get(process.env.path, function() {
console.log(JSON.stringify({throughput: 1}));
});
153 changes: 99 additions & 54 deletions benchmark/_http-benchmarkers.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,119 @@
'use strict';

const child_process = require('child_process');
const path = require('path');
const fs = require('fs');

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

function AutocannonBenchmarker() {
this.name = 'autocannon';
this.autocannon_exe = process.platform === 'win32' ?
'autocannon.cmd' :
'autocannon';
const result = child_process.spawnSync(this.autocannon_exe, ['-h']);
this.present = !(result.error && result.error.code === 'ENOENT');
}
class AutocannonBenchmarker {
constructor() {
this.name = 'autocannon';
this.executable = process.platform === 'win32' ?
'autocannon.cmd' :
'autocannon';
const result = child_process.spawnSync(this.executable, ['-h']);
this.present = !(result.error && result.error.code === 'ENOENT');
}

AutocannonBenchmarker.prototype.create = function(options) {
const args = [
'-d', options.duration,
'-c', options.connections,
'-j',
'-n',
`http://127.0.0.1:${options.port}${options.path}`
];
const child = child_process.spawn(this.autocannon_exe, args);
return child;
};
create(options) {
const args = [
'-d', options.duration,
'-c', options.connections,
'-j',
'-n',
`http://127.0.0.1:${options.port}${options.path}`
];
const child = child_process.spawn(this.executable, args);
return child;
}

AutocannonBenchmarker.prototype.processResults = function(output) {
let result;
try {
result = JSON.parse(output);
} catch (err) {
// Do nothing, let next line handle this
processResults(output) {
let result;
try {
result = JSON.parse(output);
} catch (err) {
return undefined;
}
if (!result || !result.requests || !result.requests.average) {
return undefined;
} else {
return result.requests.average;
}
}
if (!result || !result.requests || !result.requests.average) {
return undefined;
} else {
return result.requests.average;
}

class WrkBenchmarker {
constructor() {
this.name = 'wrk';
this.executable = 'wrk';
const result = child_process.spawnSync(this.executable, ['-h']);
this.present = !(result.error && result.error.code === 'ENOENT');
}

create(options) {
const args = [
'-d', options.duration,
'-c', options.connections,
'-t', 8,
`http://127.0.0.1:${options.port}${options.path}`
];
const child = child_process.spawn(this.executable, args);
return child;
}
};

function WrkBenchmarker() {
this.name = 'wrk';
this.regexp = /Requests\/sec:[ \t]+([0-9.]+)/;
const result = child_process.spawnSync('wrk', ['-h']);
this.present = !(result.error && result.error.code === 'ENOENT');
processResults(output) {
const throughputRe = /Requests\/sec:[ \t]+([0-9.]+)/;
const match = output.match(throughputRe);
const throughput = match && +match[1];
if (!isFinite(throughput)) {
return undefined;
} else {
return throughput;
}
}
}

WrkBenchmarker.prototype.create = function(options) {
const args = [
'-d', options.duration,
'-c', options.connections,
'-t', 8,
`http://127.0.0.1:${options.port}${options.path}`
];
const child = child_process.spawn('wrk', args);
return child;
};
/**
* Simple, single-threaded benchmarker for testing if the benchmark
* works
*/
class DummyBenchmarker {
constructor() {
this.name = 'dummy';
this.executable = path.resolve(__dirname, '_dummy-benchmarker.js');
this.present = fs.existsSync(this.executable);
}

create(options) {
const child = child_process.fork(this.executable, {
silent: true,
env: {
duration: options.duration,
connections: options.connections,
path: `http://127.0.0.1:${options.port}${options.path}`
}
});
return child;
}

WrkBenchmarker.prototype.processResults = function(output) {
const match = output.match(this.regexp);
const result = match && +match[1];
if (!isFinite(result)) {
return undefined;
} else {
return result;
processResults(output) {
let result;
try {
result = JSON.parse(output);
} catch (err) {
return undefined;
}
return result.throughput;
}
};
}

const http_benchmarkers = [new WrkBenchmarker(), new AutocannonBenchmarker()];
const http_benchmarkers = [
new WrkBenchmarker(),
new AutocannonBenchmarker(),
new DummyBenchmarker()
];

const benchmarkers = {};

Expand Down