From 19d023d248da46864eb149c566dde6bf3991cb65 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Thu, 2 Jun 2016 14:52:21 +0200 Subject: [PATCH 1/3] benchmark: use autocannon instead of wrk Switches all HTTP benchmarks to use autocanon (npm module) instead of wrk. This allows for running all HTTP benchmarks under Windows. --- benchmark/README.md | 11 +++----- benchmark/common.js | 45 ++++++++++++++++++------------ benchmark/http/chunked.js | 4 +-- benchmark/http/cluster.js | 3 +- benchmark/http/end-vs-write-end.js | 3 +- benchmark/http/simple.js | 3 +- 6 files changed, 35 insertions(+), 34 deletions(-) diff --git a/benchmark/README.md b/benchmark/README.md index c3d950f792e31f..3d33a3c27cb661 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -5,15 +5,12 @@ Node.js APIs. ## Prerequisites -Most of the http benchmarks require [`wrk`][wrk] and [`ab`][ab] (ApacheBench) being installed. -These may be available through your preferred package manager. +Most of the http benchmarks require [`autocannon`][autocannon] npm module +being installed. You can do this by running: -If they are not available: -- `wrk` may easily be built [from source][wrk] via `make`. -- `ab` is sometimes bundled in a package called `apache2-utils`. +`npm install -g autocannon` -[wrk]: https://github.com/wg/wrk -[ab]: http://httpd.apache.org/docs/2.2/programs/ab.html +[autocannon]: https://github.com/mcollina/autocannon ## How to run tests diff --git a/benchmark/common.js b/benchmark/common.js index 71b93d038aeb23..26422700901293 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -13,6 +13,10 @@ if (['default', 'csv', 'silent'].indexOf(outputFormat) == -1) { throw new Error('OUTPUT_FORMAT set to invalid value'); } +const autocannon_exe = process.platform === 'win32' + ? 'autocannon.cmd' + : 'autocannon'; + exports.PORT = process.env.PORT || 12346; // If this is the main module, then run the benchmarks @@ -44,11 +48,12 @@ if (module === require.main) { runBenchmarks(); } -function hasWrk() { - var result = child_process.spawnSync('wrk', ['-h']); +function hasAutocannon() { + var result = child_process.spawnSync(autocannon_exe, ['-h']); if (result.error && result.error.code === 'ENOENT') { - console.error('Couldn\'t locate `wrk` which is needed for running ' + - 'benchmarks. Check benchmark/README.md for further instructions.'); + console.error('Couldn\'t locate `autocannon` which is needed for ' + + 'running benchmarks. Check benchmark/README.md for further ' + + 'instructions.'); process.exit(-1); } } @@ -98,19 +103,17 @@ function Benchmark(fn, options) { } // benchmark an http server. -Benchmark.prototype.http = function(p, args, cb) { - hasWrk(); +Benchmark.prototype.http = function(path, duration, connections, cb) { + hasAutocannon(); var self = this; - var regexp = /Requests\/sec:[ \t]+([0-9\.]+)/; - var url = 'http://127.0.0.1:' + exports.PORT + p; - - args = args.concat(url); - var out = ''; - var child = child_process.spawn('wrk', args); + const args = ['-d', duration, '-c', connections, '-j', + 'http://127.0.0.1:' + exports.PORT + path ]; + var child = child_process.spawn(autocannon_exe, args); child.stdout.setEncoding('utf8'); + var out = ''; child.stdout.on('data', function(chunk) { out += chunk; }); @@ -120,17 +123,23 @@ Benchmark.prototype.http = function(p, args, cb) { cb(code); if (code) { - console.error('wrk failed with ' + code); + console.error('autocannon failed with ' + code); process.exit(code); } - var match = out.match(regexp); - var qps = match && +match[1]; - if (!qps) { + + try { + var result = JSON.parse(out); + } catch (err) { + // do nothing, let next line handle this + } + + if (!result || !result.requests || !result.requests.average) { console.error('%j', out); - console.error('wrk produced strange output'); + console.error('autocannon produced strange output'); process.exit(1); } - self.report(+qps); + + self.report(result.requests.average); }); }; diff --git a/benchmark/http/chunked.js b/benchmark/http/chunked.js index a61978c732233a..65b50430494c61 100644 --- a/benchmark/http/chunked.js +++ b/benchmark/http/chunked.js @@ -20,8 +20,6 @@ function main(conf) { const http = require('http'); var chunk = Buffer.alloc(conf.size, '8'); - var args = ['-d', '10s', '-t', 8, '-c', conf.c]; - var server = http.createServer(function(req, res) { function send(left) { if (left === 0) return res.end(); @@ -34,7 +32,7 @@ function main(conf) { }); server.listen(common.PORT, function() { - bench.http('/', args, function() { + bench.http('/', 10, conf.c, function() { server.close(); }); }); diff --git a/benchmark/http/cluster.js b/benchmark/http/cluster.js index 9934883f7c3fa4..84b200145b74a4 100644 --- a/benchmark/http/cluster.js +++ b/benchmark/http/cluster.js @@ -27,9 +27,8 @@ function main(conf) { setTimeout(function() { var path = '/' + conf.type + '/' + conf.length; - var args = ['-d', '10s', '-t', 8, '-c', conf.c]; - bench.http(path, args, function() { + bench.http(path, 10, conf.c, function() { w1.destroy(); w2.destroy(); }); diff --git a/benchmark/http/end-vs-write-end.js b/benchmark/http/end-vs-write-end.js index 0cdc88111de146..cfd067d794fd00 100644 --- a/benchmark/http/end-vs-write-end.js +++ b/benchmark/http/end-vs-write-end.js @@ -43,14 +43,13 @@ function main(conf) { } var method = conf.method === 'write' ? write : end; - var args = ['-d', '10s', '-t', 8, '-c', conf.c]; var server = http.createServer(function(req, res) { method(res); }); server.listen(common.PORT, function() { - bench.http('/', args, function() { + bench.http('/', 10, conf.c, function() { server.close(); }); }); diff --git a/benchmark/http/simple.js b/benchmark/http/simple.js index 5449c49be97614..def64cf4811942 100644 --- a/benchmark/http/simple.js +++ b/benchmark/http/simple.js @@ -15,9 +15,8 @@ function main(conf) { var server = require('../http_simple.js'); setTimeout(function() { var path = '/' + conf.type + '/' + conf.length + '/' + conf.chunks; - var args = ['-d', '10s', '-t', 8, '-c', conf.c]; - bench.http(path, args, function() { + bench.http(path, 10, conf.c, function() { server.close(); }); }, 2000); From d6ada4168e859eb0924b5774156c37f09be88dd8 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Wed, 15 Jun 2016 15:14:53 +0200 Subject: [PATCH 2/3] Add info about Node version used by autocannon --- benchmark/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/benchmark/README.md b/benchmark/README.md index 3d33a3c27cb661..05cb38e7eb253d 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -12,6 +12,10 @@ being installed. You can do this by running: [autocannon]: https://github.com/mcollina/autocannon +Autocannon is a Node script and will use Node executable that is in the path. +If you want to compare two HTTP benchmark runs make sure that the Node version +in the path is not altered. + ## How to run tests There are three ways to run benchmark tests: From 696153ad2235c091ecd2bc96997ccefa41b60d59 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Tue, 21 Jun 2016 11:36:33 +0200 Subject: [PATCH 3/3] Change wrk to autocannon in Makefile --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index cf10346a211768..7b68fd352a17fb 100644 --- a/Makefile +++ b/Makefile @@ -599,10 +599,10 @@ ifeq ($(XZ), 0) ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/node-$(FULLVERSION)-$(OSTYPE)-$(ARCH).tar.xz.done" endif -haswrk=$(shell which wrk > /dev/null 2>&1; echo $$?) -wrk: -ifneq ($(haswrk), 0) - @echo "please install wrk before proceeding. More information can be found in benchmark/README.md." >&2 +hasautocannon=$(shell which autocannon > /dev/null 2>&1; echo $$?) +autocannon: +ifneq ($(hasautocannon), 0) + @echo "please install autocannon before proceeding. More information can be found in benchmark/README.md." >&2 @exit 1 endif @@ -615,7 +615,7 @@ bench-crypto: all bench-tls: all @$(NODE) benchmark/common.js tls -bench-http: wrk all +bench-http: autocannon all @$(NODE) benchmark/common.js http bench-fs: all