Willem Mulder
Willem Mulder

Reputation: 13994

How come Q deferreds are so slow on Node.js?

So I created this simple test server in Node.js
Whenever I do a direct response, I get 2200 requests/second (fast!). When I only wrap a simple Q deferred around it, it drops to 580 requests/second (4 times slower!). Can anybody explain that huge difference?

// Requires
var server = require('http');
var q = require('q');

// Start server
var http = require('http');
http.createServer(function(request, response) {

    // Comment out either of two below sections

// Without deferred
// 2200 reqs/second
response.writeHead(200, {"Content-Type": "text/html"});
response.write("test");
response.end();

// Q deferred
// 580 reqs/second
var deferred = q.defer();
deferred.promise.then(function() {
    response.writeHead(200, {"Content-Type": "text/html"});
    response.write("test");
    response.end();
});
deferred.resolve();
}).listen(1234);

Upvotes: 10

Views: 3505

Answers (2)

Stuart K
Stuart K

Reputation: 3282

Edit: Performance has improved greatly since stacktraces have been turned off since Q 0.9.6. (They can be re-enabled for debugging with Q.longStackSupport = true;)

Original: Q promises are slow because they capture a full stack trace on every promise to help with debugging. This is very slow. You can turn them off with Q.longStackJumpLimit = 0; (which is likely to be the default in the next version). We found a roughly 30x speedup by turning them off. You can find out more here https://github.com/kriskowal/q#long-stack-traces

There's also been some performance work on the nextTick implementation, but I think the above is the main reason.

Upvotes: 21

Mariusz Nowak
Mariusz Nowak

Reputation: 32848

The reasons I'm aware of, are:

  1. Q uses Object.freeze, and that slows V8 by magnitudes

  2. Many nextTick calls (already mentioned in comments). This however shouldn't be that much of the case with latest Node.js version (v0.10), as there nextTick overhead is minimal.

Upvotes: 5

Related Questions