Node.js slower than Apache Node.js slower than Apache apache apache

Node.js slower than Apache


Dynamic requests

node.js is very good at handling at lot small dynamic requests(which can be hanging/long-polling). But it is not good at handling large buffers. Ryan Dahl(Author node.js) explained this one of his presentations. I recommend you to study these slides. I also watched this online somewhere.

Garbage Collector

As you can see from slide(13 from 45) it is bad at big buffers.

Slide 15 from 45:

V8 has a generational garbage collector. Moves objects around randomly. Node can’t get a pointer to raw string data to write to socket.

Use Buffer

Slide 16 from 45

Using Node’s new Buffer object, the results change.

Still not that good as for example nginx, but a lot better. Also these slides are pretty old so probably Ryan has even improved this.

CDN

Still I don't think you should be using node.js to host static files. You are probably better of hosting them on a CDN which is optimized for hosting static files. Some popular CDN's(some even free for) via WIKI.

NGinx(+Memcached)

If you don't want to use CDN to host your static files I recommend you to use Nginx with memcached instead which is very fast.


In this scenario Apache is probably doing sendfile which result in kernel sending chunk of memory data (cached by fs driver) directly to socket. In the case of node there is some overhead in copying data in userspace between v8, libeio and kernel (see this great article on using sendfile in node)

There are plenty possible scenarios where node will outperform Apache, like 'send stream of data with constant slow speed to as many tcp connections as possible'


The result of your benchmark can change in favor of node.js if you increase the concurrency and use cache in node.js

A sample code from the book "Node Cookbook":

var http = require('http');var path = require('path');var fs = require('fs');var mimeTypes = {    '.js' : 'text/javascript',    '.html': 'text/html',    '.css' : 'text/css'} ;var cache = {};function cacheAndDeliver(f, cb) {    if (!cache[f]) {        fs.readFile(f, function(err, data) {            if (!err) {                cache[f] = {content: data} ;            }            cb(err, data);        });        return;    }    console.log('loading ' + f + ' from cache');    cb(null, cache[f].content);}http.createServer(function (request, response) {    var lookup = path.basename(decodeURI(request.url)) || 'index.html';    var f = 'content/'+lookup;    fs.exists(f, function (exists) {        if (exists) {            fs.readFile(f, function(err,data) {                if (err) { response.writeHead(500);                    response.end('Server Error!'); return; }                    var headers = {'Content-type': mimeTypes[path.extname(lookup)]};                    response.writeHead(200, headers);                    response.end(data);                });            return;        }response.writeHead(404); //no such file found!response.end('Page Not Found!');});