Funcionamento interno do NodeJS
06/02/2018
Event loop? V8? Single Thread? JavaScript server side? O que diabos é isso?
Funcionamento interno do NodeJS
NodeJS é uma camada em cima de uma virtual machine chamada V8 (cool name, huh?), então antes de entendermos o que é o NodeJS vamos entender um pouco sobre a historia do V8.
No inicio da web, por volta de 1995, nasceu o JavaScript, ele foi criado
em apenas 10 dias pelo Brendan Eich, programador do Netscape na época,
só começou a ser padronizado 2~ anos depois (o nascimento do ECMAScript).
Seu primeiro nome foi Mocha, depois LiveScript e só então se tornou o JavaScript.
O primeiro compilador JavaScript se chamava SpiderMonkey (existe até hoje!),
foi desenvolvido para o navegador Netscape, e era um simples interpretador que
lia e executava códigos JavaScript, durante um bom tempo JavaScript foi praticamente um
filho bastardo, ninguém deu muita atenção e basicamente servia apenas para enviar formulários e abrir popups. (haha .)
Cerca de dez anos depois de seu nascimento o Google lançou o Google Maps, powered por
JavaScript, na época, como JavaScript era terra de ninguém, sofreu a funcionar em varios
browsers, e muitos artigos sobre padrões de compilar JavaScript surgiram, o
processo de compilar era super simples, e a partir daí começaram a olhar com outros
olhos para o nosso JS.
Só em 2008 o Google lançou sua arma open-source, chamada Chrome V8 (ou só V8 pros chegado),
a idéia era padronizar um compilador JS e "bombar" o seu novo browser.
O V8 funciona com varias threads internas, como por ex a main thread que
basicamente lê um código, manda para outra thread que compila o seu código e
quando ele estiver pronto volta para main thread e executa.
Essa thread que compila o código basicamente aplica varias optimizações,
existem pelo menos dois processos de compilação que rodam em paralelo
(Full-Codegen e Crankshaft) e produz algo pronto para ser executado em machine code,
além disso tem pelo menos mais duas threads rodando, que são a de garbage
collector e dead code elimination.
(Como o V8 cuida de processar e transformar o código vou deixar para outro post...)
Resumidamente, o V8 processa códigos JavaScript. Pelo seguinte processo: ele começa a processar o seu código, manda para outra thread compilar, e a thread principal fica aberta para novos processamentos até ter sua resposta de volta, e só quando seu código termina de compilar ela volta a processar ele.
OK, faz sentido... e o NodeJS?
Calma, calma! Vamos chegar lá... temos que falar um pouco sobre a libev (ou libevent) e o Microsoft IOCP.
Esse vai ser bem rápido, pois não tenho muita historia pra eles :P
Basicamente, essas duas libraries fornecem uma API para executar
funções quando determinados eventos ou timeouts acontecerem, libev para UNIX e IOCP para Windows.
Huum.. to começando a entender, o V8 processa o JavaScript e a libev/IOCP chamam meus callbacks no Node quando terminar?
Quase isso! A libev/IOCP estão meio que deprecated theses days, delas
nasceu a libuv que é o que o NodeJS usa no momento.
Continuando... em 2009 Ryan Dahl juntou essas duas tecnologias para criar o NodeJS.
Basicamente, o V8 processa o JS, transforma em machine code, a libuv
manda executar e anexa um callback a isso, quando pronto, chama esse callback que retorna pra userland.
Esse vai e volta é o chamado Event Loop, ou IO não bloqueante do NodeJS.
Quando escrevemos um código ou script para NodeJS o event loop pega esse código,
processa ele, manda para a libuv e vai atrás de mais códigos para mandar pro v8 e
para a libuv, e assim vai.
Mas peraí, ouvi dizer que NodeJS é single thread...
Isso! Você está correto (em partes). Pois, NodeJS mantém uma única
thread aberta para o seu codigo, um EventLoop na libuv (não é o NodeJS de fato que tem o event loop, ele cria e gerencia um na libuv).
Achei essa imagem que representa bem esse flow:
Refs:
Fez algum sentido? :)