node.js


¿Rápido como el rayo?

Vuestro anfitrión esta noche



Pequeño Chambelán
Cacharreador impenitente
@pinchito, alexfernandez, alejandrofer

Lo que vamos a ver


  • Introducción a memcached

  • Presentando nodecached

  • Mind your microseconds

  • Microperfilado

  • Demo

  • Conclusiones

Introducing Memcached


Memcached es uno de los
grandes inventos de la humanidad


Caché remota en memoria

Base de datos clave-valor en memoria

API básico de Memcached

set [key] [flags] [exptime] [bytes]\r\n
[data block]\r\n
\=> STORED / NOT_STORED

almacena un valor en memoria

get [key]* \r\n
\=> VALUE [key] [flags] [bytes]\r\n
[data block]\r\n
END\r\n

saca uno o más valores de memoria

delete [key]
\=> DELETED / NOT_FOUND

borra un valor de memoria

Fuente: protocol.txt

Mi misión


Memcached es un gran invento

Me gusta así que lo copio


Clon usando node.js: nodecached


C contra JavaScript: ¿es posible?

Claro: node.js es muy rápido

o eso dicen

claro que fíate tú de lo que dicen por ahí

El campo de batalla

El santo grial:

peticiones por segundo (rps, req/s):


mc-benchmark: el rapero geek

escrita por el creador de Redis

Salvatore Sanfilippo (antirez)

compilada a partir del código

Resultados preliminares


nodecached:

set: 25 kreq/s

get: 29 kreq/s


memcached:

set: 67 kreq/s

get: 76 kreq/s


Grandes Precursores

Almirante Grace Hopper

Descubridora del primer "bug" (chiste)

Mind your nanoseconds


Un nanosegundo → 30 cm


En un cable: 2/3 de la velocidad de la luz

Un nanosegundo → 20 cm

1 GHz → 1 ns


3 GHz → 0.3 ns → 10 cm

En un cable: 0.3 ns → 6 cm

Tamaño de un Intel Nehalem: 1.6 cm

Mind your microseconds

1 µs = 300 m

~ 1 llamada al sistema en node.js

¡Un millón de oportunidades por segundo!

Convertimos a microsegundos


nodecached:

set: 25 kreq/s = 40 µs/req

get: 29 kreq/s ~ 34 µs/req

memcached:

set: 67 kreq/s ~ 15 µs/req

get: 76 kreq/s ~ 13 µs/req


Gráficamente



memcached       nodecached

Perfilado tradicional

Salida muy farragosa

y distorsionada por la medida

Introducing Microprofiler


Perfilado a nivel de microsegundos


Usa el temporizador de node
de alta resolución (nanosegundos)
process.hrtime()


Pinta estadísticas


microprofiler en GitHub

API de microprofiler


var profiler = require('microprofiler');
profiler.measureFrom(start, name, timesToShow) 

Mide el valor para name  desde el tiempo en start


profiler.show(name);

Muestra los resultados para name


profiler.disable();

Deshabilita el profiler

Ejemplo de uso


var profiler = require('../index.js');

var total = 1000000;
var s = 0;
for (var i = 0; i < total; i++)
{
    var start = process.hrtime();
    s += i;
    profiler.measureFrom(start, 'stuff', total);
}    


Salida:

[Sat Mar 22 2014 19:16:16 GMT+0100 (CET)] INFO
Profiling stuff: 1000000 requests, mean time: 0.39 µs, rps: 2547787


Demo time!




¿Quién le teme al riesgo?

Resultado final


Alternate ending



Conclusiones

No hay balas de plata


Se puede mejorar el código un 10%
¡con mucho trabajo!


No controlamos la mayor parte del tiempo
(20 de 30 µs son entrada/salida)

Ley de Amdahl: gran mejora → poco resultado


Los resultados son bastante ruidosos

Una cosita más...



No nos vengamos abajo

Caso real


Proxy para tráfico pesado (varios kreq/s)


Servidor http: 400 req/s

Servidor de sockets: 1000 req/s

Pool de conexiones: 2700 req/s

Node 0.8: 3400 req/s

Test con dos máquinas: 5440 req/s

Test con dos cores: 7107 req/s

Debería llegar al doble: 14 kreq/s

Más Conclusiones


Cuidado con las librerías que usas (http vs sockets)


Los tiempos deben ser siempre coherentes


El trabajo de optimización es costoso


... pero a veces es necesario


... ¡y gratificante!

¡Gracias!


https://slid.es/alexfernandez/nodejs-rapido-rayo

¿Preguntas?

Node.js: ¿rápido como el rayo?

By Alex Fernández

Node.js: ¿rápido como el rayo?

Charla para Node.js Madrid el 2014-04-23.

  • 4,701