|
@ -1,74 +1,119 @@ |
|
|
'use strict'; |
|
|
'use strict'; |
|
|
|
|
|
|
|
|
const child_process = require('child_process'); |
|
|
const child_process = require('child_process'); |
|
|
|
|
|
const path = require('path'); |
|
|
|
|
|
const fs = require('fs'); |
|
|
|
|
|
|
|
|
// The port used by servers and wrk
|
|
|
// The port used by servers and wrk
|
|
|
exports.PORT = process.env.PORT || 12346; |
|
|
exports.PORT = process.env.PORT || 12346; |
|
|
|
|
|
|
|
|
function AutocannonBenchmarker() { |
|
|
class AutocannonBenchmarker { |
|
|
this.name = 'autocannon'; |
|
|
constructor() { |
|
|
this.autocannon_exe = process.platform === 'win32' ? |
|
|
this.name = 'autocannon'; |
|
|
'autocannon.cmd' : |
|
|
this.executable = process.platform === 'win32' ? |
|
|
'autocannon'; |
|
|
'autocannon.cmd' : |
|
|
const result = child_process.spawnSync(this.autocannon_exe, ['-h']); |
|
|
'autocannon'; |
|
|
this.present = !(result.error && result.error.code === 'ENOENT'); |
|
|
const result = child_process.spawnSync(this.executable, ['-h']); |
|
|
} |
|
|
this.present = !(result.error && result.error.code === 'ENOENT'); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
AutocannonBenchmarker.prototype.create = function(options) { |
|
|
create(options) { |
|
|
const args = [ |
|
|
const args = [ |
|
|
'-d', options.duration, |
|
|
'-d', options.duration, |
|
|
'-c', options.connections, |
|
|
'-c', options.connections, |
|
|
'-j', |
|
|
'-j', |
|
|
'-n', |
|
|
'-n', |
|
|
`http://127.0.0.1:${options.port}${options.path}` |
|
|
`http://127.0.0.1:${options.port}${options.path}` |
|
|
]; |
|
|
]; |
|
|
const child = child_process.spawn(this.autocannon_exe, args); |
|
|
const child = child_process.spawn(this.executable, args); |
|
|
return child; |
|
|
return child; |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
AutocannonBenchmarker.prototype.processResults = function(output) { |
|
|
processResults(output) { |
|
|
let result; |
|
|
let result; |
|
|
try { |
|
|
try { |
|
|
result = JSON.parse(output); |
|
|
result = JSON.parse(output); |
|
|
} catch (err) { |
|
|
} catch (err) { |
|
|
// Do nothing, let next line handle this
|
|
|
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 { |
|
|
class WrkBenchmarker { |
|
|
return result.requests.average; |
|
|
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() { |
|
|
processResults(output) { |
|
|
this.name = 'wrk'; |
|
|
const throughputRe = /Requests\/sec:[ \t]+([0-9.]+)/; |
|
|
this.regexp = /Requests\/sec:[ \t]+([0-9.]+)/; |
|
|
const match = output.match(throughputRe); |
|
|
const result = child_process.spawnSync('wrk', ['-h']); |
|
|
const throughput = match && +match[1]; |
|
|
this.present = !(result.error && result.error.code === 'ENOENT'); |
|
|
if (!isFinite(throughput)) { |
|
|
|
|
|
return undefined; |
|
|
|
|
|
} else { |
|
|
|
|
|
return throughput; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
WrkBenchmarker.prototype.create = function(options) { |
|
|
/** |
|
|
const args = [ |
|
|
* Simple, single-threaded benchmarker for testing if the benchmark |
|
|
'-d', options.duration, |
|
|
* works |
|
|
'-c', options.connections, |
|
|
*/ |
|
|
'-t', 8, |
|
|
class TestDoubleBenchmarker { |
|
|
`http://127.0.0.1:${options.port}${options.path}` |
|
|
constructor() { |
|
|
]; |
|
|
this.name = 'test-double'; |
|
|
const child = child_process.spawn('wrk', args); |
|
|
this.executable = path.resolve(__dirname, '_test-double-benchmarker.js'); |
|
|
return child; |
|
|
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) { |
|
|
processResults(output) { |
|
|
const match = output.match(this.regexp); |
|
|
let result; |
|
|
const result = match && +match[1]; |
|
|
try { |
|
|
if (!isFinite(result)) { |
|
|
result = JSON.parse(output); |
|
|
return undefined; |
|
|
} catch (err) { |
|
|
} else { |
|
|
return undefined; |
|
|
return result; |
|
|
} |
|
|
|
|
|
return result.throughput; |
|
|
} |
|
|
} |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
const http_benchmarkers = [new WrkBenchmarker(), new AutocannonBenchmarker()]; |
|
|
const http_benchmarkers = [ |
|
|
|
|
|
new WrkBenchmarker(), |
|
|
|
|
|
new AutocannonBenchmarker(), |
|
|
|
|
|
new TestDoubleBenchmarker() |
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
const benchmarkers = {}; |
|
|
const benchmarkers = {}; |
|
|
|
|
|
|
|
|