I was not terribly surprised to find that the relatively new server-side Dart HTTP server was significantly slower than the more established node.js / express.js. A simple express.js server was, in fact, 20% faster at serving static files than similar Dart code. That is about what I would expect, but before moving on, I would like to make sure that I am making an apples-to-apples comparison. That is, I would like to make sure that the express.js version is not doing any caching.
After a bit of investigation, I discover the
staticCache middleware in express (which is actually part of the underlying connect.js). So I add this to my app's configuration:app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.staticCache());
app.use(express.static(__dirname + '/public'));
});
Then re-run my benchmarks:cstrom@londo:~/repos/dart-comics$ ab -n 10000 -c 2 http://localhost:3000/scripts/web/main.dart ... Requests per second: 2199.68 [#/sec] (mean) Time per request: 0.909 [ms] (mean)Compare that with yesterday's non-cache results:
cstrom@londo:~/repos/dart-comics$ ab -n 10000 -c 2 http://localhost:3000/scripts/web/main.dart ... Requests per second: 1602.96 [#/sec] (mean) Time per request: 1.248 [ms] (mean)And it is clear that node.js caching only makes the difference between server-side Dart and node.js that much bigger.
I am not going to dwell on the differences too much and definitely do not want to spend time optimizing Dart code further. I only want to implement a pure Dart backend for my sample application. That said, I am curious if route matching is causing most of the slow down or if it is just the underlying filesystem calls that are trouble.
So I rewrite my
addRequetHandler() so that the route matching function always returns true and then let the response function do its thing:#import('dart:io');
main() {
HttpServer app = new HttpServer();
var last_path;
app.addRequestHandler(
(req) => true,
(req, res) {
var file = new File(publicPath(req.path));
var stream = file.openInputStream();
stream.pipe(res.outputStream);
}
);
app.listen('0.0.0.0', 8000);
}With that, I find the following numbers:cstrom@londo:~/repos/dart-comics$ ab -n 10000 -c 2 http://localhost:8000/scripts/web/main.dart ... Requests per second: 1650.30 [#/sec] (mean) Time per request: 1.212 [ms] (mean)Which is a better than my best Dart solution from yesterday with a routing function:
Requests per second: 1566.07 [#/sec] (mean) Time per request: 1.277 [ms] (mean)Actually, that is also better than the non-caching express.js solution as well:
cstrom@londo:~/repos/dart-comics$ ab -n 10000 -c 2 http://localhost:3000/scripts/web/main.dart ... Requests per second: 1602.96 [#/sec] (mean) Time per request: 1.248 [ms] (mean)So, if I cared about performance, I might look to improve the route matching function first. Most of my handler is spending its time in the response callback, but there is a good 20% overhead in my file-existence routing callback. It's a good thing I do not care. Instead of chasing numbers, tomorrow I will pick back up trying to replace functionality in my sample app.
Day #570
No comments:
Post a Comment