En realidad, su carga de trabajo no está realmente limitada a E/S:está limitada a la CPU debido al costo de la generación de páginas dinámicas basadas en jade. No puedo adivinar la complejidad de su plantilla de jade, pero incluso con plantillas simples, generar páginas HTML es costoso.
Para mis pruebas utilicé esta plantilla:
html(lang="en")
head
title Example
body
h1 Jade - node template engine
#container
ul#users
each user in items
li User:#{user}
Agregué 100 cadenas ficticias a la clave de elementos en Redis.
En mi caja, obtengo 475 req/s con CPU node.js al 100 % (lo que significa un consumo de CPU del 50 % en esta caja de doble núcleo). Reemplacemos:
res.render( 'index', { items: items } );
por:
res.send( '<html lang="en"><head><title>Example</title></head><body><h1>Jade - node template engine</h1><div id="container"><ul id="users"><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li></ul></div></body></html>' );
Ahora, el resultado del benchmark está cerca de 2700 req/s. Entonces, el cuello de botella se debe claramente al formato de la página HTML.
Usar el paquete de clúster en esta situación es una buena idea y es sencillo. El código se puede modificar de la siguiente manera:
var cluster = require('cluster')
if ( cluster.isMaster ) {
for ( var i=0; i<2; ++i )
cluster.fork();
} else {
var
express = require( 'express' ),
app = express.createServer(),
redis = require( 'redis' ).createClient();
app.configure( function() {
app.set( 'view options', { layout: false } );
app.set( 'view engine', 'jade' );
app.set( 'views', __dirname + '/views' );
app.use( express.bodyParser() );
});
function log( what ) { console.log( what ); }
app.get( '/', function( req, res ) {
redis.lrange( 'items', 0, 50, function( err, items ) {
if( err ) { log( err ); } else {
res.render( 'index', { items: items } );
}
});
});
app.listen( 8080 );
}
Ahora el resultado del benchmark está cerca de 750 req/s con un consumo de CPU del 100 % (para comparar con los 475 req/s iniciales).