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
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