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

7.x: new router and middleware system #1561

Merged
merged 4 commits into from Feb 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions Makefile
Expand Up @@ -24,7 +24,6 @@ NODEUNIT := ./node_modules/.bin/nodeunit
MOCHA := ./node_modules/.bin/mocha
NODECOVER := ./node_modules/.bin/cover
DOCS_BUILD := ./tools/docsBuild.js
BENCHMARK := ./benchmark/index.js
NPM := npm
NODE := node
PRETTIER := ./node_modules/.bin/prettier
Expand Down Expand Up @@ -74,7 +73,7 @@ docs-build:

.PHONY: benchmark
benchmark:
@($(NODE) $(BENCHMARK))
@(cd ./benchmark && $(NPM) i && $(NODE) index.js)

include ./tools/mk/Makefile.deps
include ./tools/mk/Makefile.targ
33 changes: 33 additions & 0 deletions benchmark/benchmarks/middleware.js
@@ -0,0 +1,33 @@
'use strict';

var restify = process.argv.includes('version=head')
? require('../../lib')
: require('restify');

var server = restify.createServer();
var path = '/';
var port = 3000;

module.exports = {
url: 'http://localhost:' + port + path
};

function handler(req, res, next) {
next();
}

for (var i = 0; i < 10; i++) {
server.pre(handler);
}

for (var j = 0; j < 10; j++) {
server.use(handler);
}

server.get(path, function get(req, res) {
res.send('hello world');
});

if (!module.parent) {
server.listen(port);
}
12 changes: 10 additions & 2 deletions benchmark/benchmarks/response-json.js
Expand Up @@ -5,9 +5,17 @@ var restify = process.argv.includes('version=head')
: require('restify');

var server = restify.createServer();
var path = '/';
var port = 3000;

server.get('/', function onRequest(req, res) {
module.exports = {
url: 'http://localhost:' + port + path
};

server.get(path, function onRequest(req, res) {
res.send({ hello: 'world' });
});

server.listen(3000);
if (!module.parent) {
server.listen(port);
}
12 changes: 10 additions & 2 deletions benchmark/benchmarks/response-text.js
Expand Up @@ -5,9 +5,17 @@ var restify = process.argv.includes('version=head')
: require('restify');

var server = restify.createServer();
var path = '/';
var port = 3000;

server.get('/', function onRequest(req, res) {
module.exports = {
url: 'http://localhost:' + port + path
};

server.get(path, function onRequest(req, res) {
res.send('hello world');
});

server.listen(3000);
if (!module.parent) {
server.listen(port);
}
132 changes: 132 additions & 0 deletions benchmark/benchmarks/router-heavy.js
@@ -0,0 +1,132 @@
'use strict';

var restify = process.argv.includes('version=head')
? require('../../lib')
: require('restify');

var server = restify.createServer();
var path = '/whiskeys/scotch/islay/lagavulin/16-years/50';
Copy link
Member

Choose a reason for hiding this comment

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

🍺

Copy link
Member Author

Choose a reason for hiding this comment

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

🥃

var methods = ['post', 'put', 'get', 'del', 'patch'];
var _ = require('lodash');
var port = 3000;

// Disabling cache: it's not fair as it aims to the worst case, when
// cache hit ratio is 0%. However, it's still better than the worst
// as it doesn't require extra time to maintain the LRU cache.
// There is no other way to simulate 100+ different endpoint
// calls with the current benchmark suite.
if (!process.argv.includes('version=head')) {
server.router.cache = {
get: function get() {
return null;
},
set: function get() {
return null;
},
dump: function get() {
return [];
}
};
}

module.exports = {
url: 'http://localhost:' + port + path
};

var routes = {
beers: {
ale: {
'pale-ale': {
'american-pale-ale': [],
'indian-pale-ale': []
},
lambic: [],
stout: {
'american-porter': [],
'imperial-stout': [],
'irish-stout': []
}
},
lager: {
'german-lager': {
marzen: []
},
pilsner: {
'german-pilsner': []
}
}
},

whiskeys: {
american: {
bourbon: {
kentchuky: {
'jim-beam': ['jim-beam', 'bookers', 'old-crow'],
'makers-mark': ['makers-mark'],
'woodford-reserve': ['woodford-reserve']
},
tennessee: {
'jack-daniels': ['jack-daniels']
}
},
rye: {
'beam-suntory': ['jim-beam-rye', 'knob-creek']
}
},
irish: {
'single-malt': {
bushmills: ['bushmills'],
connemare: ['connemare']
},
'single-pot': {
redbreast: ['redbreast'],
jameson: ['jameson-15-year']
}
},
japanese: {
nikka: ['coffeey-malt', 'blended', 'from-the-barrel'],
hibiki: ['japanese-harmony'],
yamazakura: ['blended']
},
scotch: {
islay: {
bruichladdich: ['25-years', 'islay-barley-2009'],
octomore: ['7.2', 'islay-barley-8.3'],
laphroaig: ['lore', '15-years', 'four-oak'],
lagavulin: ['distillers-edition', '8-years', '16-years']
}
}
}
};

function handler(req, res) {
res.send('hello');
}

function attachRoute(parent, routeConfig) {
_.map(routeConfig, function map(route, routeKey) {
var pathChunk = _.isString(routeKey) ? routeKey : route;
var routePath = parent + '/' + pathChunk;

methods.forEach(function forEach(method) {
server[method](routePath, handler);
});

if (_.isObject(route) || _.isArray(route)) {
attachRoute(routePath, route);
}
if (_.isString(route)) {
for (var i = 0; i <= 100; i++) {
methods.forEach(function forEach(method) {
server[method](routePath + '/' + i, handler);
});
}
}
});
}

attachRoute('', routes);

if (!module.parent) {
server.listen(port);
}
7 changes: 6 additions & 1 deletion benchmark/index.js
Expand Up @@ -5,7 +5,12 @@ var inquirer = require('inquirer');
var bench = require('./lib/bench');
var stableVersion = require('restify/package.json').version;

var BENCHMARKS = ['response-json', 'response-text'];
var BENCHMARKS = [
'response-json',
'response-text',
'router-heavy',
'middleware'
];

function select(callback) {
var choices = BENCHMARKS.map(function map(name) {
Expand Down
2 changes: 1 addition & 1 deletion benchmark/lib/autocannon.js
Expand Up @@ -22,7 +22,7 @@ function writeResult(handler, version, result) {

function fire(opts, handler, version, save, cb) {
opts = opts || {};
opts.url = 'http://localhost:3000';
opts.url = opts.url || 'http://localhost:3000';

var instance = autocannon(opts, function onResult(err, result) {
if (err) {
Expand Down
10 changes: 8 additions & 2 deletions benchmark/lib/bench.js
Expand Up @@ -14,6 +14,7 @@ function runBenchmark(opts, handler, version, cb) {

var spinner = ora('Started ' + version + '/' + handler).start();
var modulePath = path.join(__dirname, '../benchmarks', handler);
var url = require(modulePath).url;
var forked = fork(modulePath, ['version=' + version]);

pipeline(
Expand All @@ -24,8 +25,12 @@ function runBenchmark(opts, handler, version, cb) {
spinner.text =
'Warming ' + version + '/' + handler + ' for 5s';

var fireOpts = Object.assign({}, opts, {
duration: 5,
url: url
});
autocannon.fire(
Object.assign({}, opts, { duration: 5 }),
fireOpts,
handler,
version,
false,
Expand All @@ -48,7 +53,8 @@ function runBenchmark(opts, handler, version, cb) {
's';
}

autocannon.fire(opts, handler, version, true, callback);
var fireOpts = Object.assign({}, opts, { url: url });
autocannon.fire(fireOpts, handler, version, true, callback);
}
]
},
Expand Down
19 changes: 19 additions & 0 deletions benchmark/package.json
@@ -0,0 +1,19 @@
{
"name": "restify-benchmark",
"homepage": "http://restifyjs.com",
"description": "Restify benchmark",
"version": "0.0.0",
"private": true,
"main": "index.js",
"engines": {
"node": ">=0.10"
},
"dependencies": {
"restify": "*"
},
"devDependencies": {},
"license": "MIT",
"scripts": {
"start": "node indec"
}
}