Node.js Runtime Internals
Trilha #4 do plano de estudos. Como o Node.js realmente executa o código por baixo dos panos.
Event Loop (libuv)
Fases em ordem, por iteração (tick):
- timers — callbacks de
setTimeout/setInterval. - pending callbacks — alguns callbacks de I/O adiados.
- idle/prepare — interno.
- poll — busca novos eventos de I/O; executa callbacks de I/O.
- check — callbacks de
setImmediate. - close callbacks — ex.:
socket.on('close').
- Microtasks rodam entre fases e esvaziam completamente:
process.nextTick(fila própria, prioridade máxima) e depois Promises (then/catch/finally). setImmediate(check) vssetTimeout(0)(timers): a ordem depende do contexto; dentro de um callback de I/O,setImmediateroda primeiro.
console.log("1");
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
Promise.resolve().then(() => console.log("promise"));
process.nextTick(() => console.log("nextTick"));
console.log("2");
// 1, 2, nextTick, promise, (timeout/immediate conforme contexto)
libuv & thread pool
- Node é single-threaded para JS, mas o libuv usa um thread pool
(padrão 4,
UV_THREADPOOL_SIZE) para: fs, DNS (dns.lookup),crypto.pbkdf2,zlib. - Bloquear o event loop (loop pesado de CPU,
*Sync) trava todas as conexões. Offload paraworker_threadsou fila (ver nodejs-high-concurrency).
V8
- Call stack + heap; GC geracional (new space / old space), scavenge vs mark-sweep-compact.
- Hidden classes / inline caches — manter shape dos objetos estável ajuda o JIT.
- Flags úteis:
--max-old-space-size,--inspect(DevTools), heap snapshots.
Streams & backpressure
Readable/Writable/Transform/Duplex;pipe/pipeline.- Backpressure:
write()retornafalse→ pare até o eventodrain. - Use streams para arquivos/respostas grandes e evitar estourar a memória.
Concorrência & processos
worker_threads— paralelismo de CPU, memória compartilhável (SharedArrayBuffer).cluster/ PM2 — múltiplos processos compartilhando porta (escala em cores).child_process— spawn de processos externos.
Diagnóstico de memória
- Vazamentos comuns: listeners não removidos, closures retendo refs, caches sem limite, timers órfãos.
- Ferramentas:
--inspect+ Chrome DevTools, heap snapshots,clinic.js,--prof.
Perguntas de entrevista (treinar)
- Explique as fases do event loop. Onde entram microtasks?
process.nextTickvssetImmediatevssetTimeout(0)?- O que o thread pool do libuv processa?
- O que acontece se você bloquear o event loop? Como evitar?
- O que é backpressure em streams?
Relacionadas: nodejs-high-concurrency · express-middleware-chain · plano de estudos.