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