Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Funcionamento interno do Node.js e boas práticas

Kirmayr Tomaz
October 19, 2017
62

Funcionamento interno do Node.js e boas práticas

Atualmente, o Node.js conquista uma maior popularidade a cada dia. Com tantos frameworks e DOM (Desenvolvimento Orientada a Modinha), acabamos deixando de lado como é seu funcionamento por baixo dos panos, além de práticas que podem afetar a performance de uma aplicação. Afinal, você sabe exatamente o que é o Node.js?. Talk realizada no TDC SP de 2017

Kirmayr Tomaz

October 19, 2017
Tweet

Transcript

  1. Sobre mim Kirmayr Tomaz • De Manaus/AM • Bacharel em

    Sistemas de Informação - UFAM • Organizador do Femug-AM • Mentor no Traning Center @kirmayrtomaz [email protected]
  2. Sobre mim Kirmayr Tomaz • De Manaus/AM • Bacharel em

    Sistemas de Informação - UFAM • Organizador do Femug-AM • Mentor no Traning Center @kirmayrtomaz [email protected]
  3. SUMÁRIO • Node Interno ◦ Conceitos base ◦ Estrutura do

    Node.js ◦ Libuv ◦ V8 •TurboFan •Ignition ◦ APIs
  4. Node.js Terminologia • Single Thread • Paralelismo e concorrência •

    Síncrono e assíncrono • I/O não bloqueante • Orientada a Eventos
  5. Estrutura do Node.js Dependências Internas • Libuv • V8 •

    C-iris • Crypto • HTTP-parse • Zlib • OpenSSL Ferramentas • npm • gyp • gtest
  6. Libuv • Event loop • TCP e UDP socket assíncrono

    • DNS assíncrono • Operações assíncronas com arquivos • Eventos de arquivos • Thread pool • Internal Process Communication (IPC) compartilhado entre os sockets • Child processes
  7. console.log(‘script start’); const isType = (value,type) => typeof value ===

    type; const isNumber= (num) => isType(num, ‘number’) const number = isNumber(3) console.log(number) console.log(‘script stop’) CallStack console
  8. console.log(‘script start’); const isType = (value,type) => typeof value ===

    type; const isNumber= (num) => isType(num, ‘number’) const number = isNumber(3) console.log(number) console.log(‘script stop’) CallStack IsNumber IsType
  9. CallStack console.log(‘script start’); const isType = (value,type) => typeof value

    === type; const isNumber= (num) => isType(num, ‘number’) const number = isNumber(3) console.log(number) console.log(‘script stop’) console
  10. CallStack console.log(‘script start’); const isType = (value,type) => typeof value

    === type; const isNumber= (num) => isType(num, ‘number’) const number = isNumber(3) console.log(number) console.log(‘script stop’) console
  11. Task Queue • Background Thread (Pull Thread) • Task Queue

    - Local onde os callbacks ficam aguardando serem chamados • Event Loop
  12. console.log(‘script start’); setTimeout(( )=> console.log(“setTimeout 1’’),0); const isType = (value,type)

    => typeof value === type; const isNumber= (num) => isType(num, ‘number’) const number = isNumber(3); console.log(number); setTimeout(( )=> console.log(“setTimeout 2’’),0); console.log(‘script stop’); CallStack Background Thread Task Queue Event Loop console
  13. console.log(‘script start’); setTimeout(( )=> console.log(“setTimeout 1’’),0); const isType = (value,type)

    => typeof value === type; const isNumber= (num) => isType(num, ‘number’); const number = isNumber(3); console.log(number); setTimeout(( )=> console.log(“setTimeout 2’’),0); console.log(‘script stop’); CallStack Background Thread Task Queue Event Loop setTimeout1 setTimeout 1
  14. console.log(‘script start’); setTimeout(( )=> console.log(“setTimeout 1’’),0); const isType = (value,type)

    => typeof value === type; const isNumber= (num) => isType(num, ‘number’); const number = isNumber(3); console.log(number); setTimeout(( )=> console.log(“setTimeout 2’’),0); console.log(‘script stop’); CallStack Background Thread Task Queue Event Loop setTimeout1 IsNumber IsType
  15. console.log(‘script start’); setTimeout(( )=> console.log(“setTimeout 1’’),0); const isType = (value,type)

    => typeof value === type; const isNumber= (num) => isType(num, ‘number’) const number = isNumber(3); console.log(number); setTimeout(( )=> console.log(“setTimeout 2’’),0); console.log(‘script stop’); CallStack Background Thread Task Queue Event Loop setTimeout1 console
  16. console.log(‘script start’); setTimeout(( )=> console.log(“setTimeout 1’’),0); const isType = (value,type)

    => typeof value === type; const isNumber= (num) => isType(num, ‘number’) const number = isNumber(3); console.log(number); setTimeout(( )=> console.log(“setTimeout 2’’),0); console.log(‘script stop’); CallStack Background Thread Task Queue Event Loop setTimeout1 setTimeout2 setTimeout2
  17. CallStack Background Thread Task Queue Event Loop setTimeout1 setTimeout2 console.log(‘script

    start’); setTimeout(( )=> console.log(“setTimeout 1’’),0); const isType = (value,type) => typeof value === type; const isNumber= (num) => isType(num, ‘number’) const number = isNumber(3) console.log(number) setTimeout(( )=> console.log(“setTimeout 2’’),0); console.log(‘script stop’) console
  18. CallStack Background Thread Task Queue Event Loop setTimeout1 setTimeout2 setTimeout1

    setTimeout2 console.log(‘script start’); setTimeout(( )=> console.log(“setTimeout 1’’),0); const isType = (value,type) => typeof value === type; const isNumber= (num) => isType(num, ‘number’); const number = isNumber(3); console.log(number); setTimeout(( )=> console.log(“setTimeout 2’’),0); console.log(‘script stop’); setTimeout1
  19. CallStack Background Thread Task Queue Event Loop setTimeout2 console.log(‘script start’);

    setTimeout(( )=> console.log(“setTimeout 1’’),0); const isType = (value,type) => typeof value === type; const isNumber= (num) => isType(num, ‘number’); const number = isNumber(3); console.log(number); setTimeout(( )=> console.log(“setTimeout 2’’),0); console.log(‘script stop’); setTimeout2
  20. Task Queue • Macro Task - São processadas pelo Event

    Loop • Micro Task - são programadas para executar após a execução principal do código
  21. CallStack Background Thread Task Queue / MacroTask MicroTask Event Loop

    console.log(‘script start’); setTimeout( function ( ) { console.log(“setTimeout 1’’); },0); Promise.resolve( ).then( function ( ) { console.log(‘promise 1’); }).then( function ( ) { console.log(‘promise 2’); }) console.log(‘script stop’); console
  22. CallStack Background Thread Task Queue / MacroTask MicroTask Event Loop

    setTimeout console.log(‘script start’); setTimeout( function ( ) { console.log(“setTimeout 1’’); },0); Promise.resolve( ).then( function ( ) { console.log(‘promise 1’); }).then( function ( ) { console.log(‘promise 2’); }) console.log(‘script stop’); setTimeout
  23. CallStack Background Thread Task Queue / MacroTask MicroTask Event Loop

    setTimeout Promise console.log(‘script start’); setTimeout( function ( ) { console.log(“setTimeout 1’’); },0); Promise.resolve( ).then( function ( ) { console.log(‘promise 1’); }).then( function ( ) { console.log(‘promise 2’); }) console.log(‘script stop’); Promise
  24. CallStack Background Thread Task Queue / MacroTask MicroTask Event Loop

    setTimeout Promise then Promise then console.log(‘script start’); setTimeout( function ( ) { console.log(“setTimeout 1’’); },0); Promise.resolve( ).then( function ( ) { console.log(‘promise 1’); }).then( function ( ) { console.log(‘promise 2’); }) console.log(‘script stop’); console
  25. CallStack Background Thread Task Queue / MacroTask MicroTask Event Loop

    setTimeout Promise then console.log(‘script start’); setTimeout( function ( ) { console.log(“setTimeout 1’’); },0); Promise.resolve( ).then( function ( ) { console.log(‘promise 1’); }).then( function ( ) { console.log(‘promise 2’); }) console.log(‘script stop’); Promise then Promise then
  26. CallStack Background Thread Task Queue / MacroTask MicroTask Event Loop

    setTimeout Promise then console.log(‘script start’); setTimeout( function ( ) { console.log(“setTimeout 1’’); },0); Promise.resolve( ).then( function ( ) { console.log(‘promise 1’); }).then( function ( ) { console.log(‘promise 2’); }) console.log(‘script stop’); Promise then
  27. CallStack Background Thread Task Queue / MacroTask MicroTask Event Loop

    setTimeout setTimeout console.log(‘script start’); setTimeout( function ( ) { console.log(“setTimeout 1’’); },0); Promise.resolve( ).then( function ( ) { console.log(‘promise 1’); }).then( function ( ) { console.log(‘promise 2’); }) console.log(‘script stop’); setTimeout
  28. V8

  29. V8 • Projeto Open-source desenvolvida pela Google, para interpretar código

    javascript super performático, escrito em C++ utilizado pelo google Chrome, Node.js e afins.
  30. V8 • O javascript possui pouca informação sobre quais são

    os tipos dos valores na sua aplicação, sendo que eles podem mudar em tempo de execução • Tipagem dinâmica pode ser um dos principais recursos da linguagem, mas também é um dos principais motivos pelos quais muitas vezes executa mais lento que linguagens estaticamente tipadas
  31. V8 - Classes Ocultas • Uma das formas para minimizar

    esse problema é utilizando as classes ocultas
  32. function person (name, age ) { //Criando classe oculta A

    this.name = name; //Criando classe oculta B this.age = age; } //Utilizando classe oculta B const developer = person(‘developer’, 15); //Utilizando classe oculta B const conference = person(‘conference’, 15); //Criando e Utilizando classe oculta C developer.linguagem = “javascript”; Person Object Initial Hidden Class P0
  33. function person (name, age ) { //Criando classe oculta A

    this.name = name; //Criando classe oculta B this.age = age; } //Utilizando classe oculta B const developer = person(‘developer’, 15); //Utilizando classe oculta B const conference = person(‘conference’, 15); //Criando e Utilizando classe oculta C developer.linguagem = “javascript”; Person Object Initial Hidden Class P0 Initial Hidden Class PA
  34. Person Object Initial Hidden Class PA Initial Hidden Class PB

    Initial Hidden Class P0 function person (name, age ) { //Criando classe oculta A this.name = name; //Criando classe oculta B this.age = age; } //Utilizando classe oculta B const developer = person(‘developer’, 15); //Utilizando classe oculta B const conference = person(‘conference’, 15); //Criando e Utilizando classe oculta C developer.linguagem = “javascript”;
  35. function person (name, age ) { //Criando classe oculta A

    this.name = name; //Criando classe oculta B this.age = age; } //Utilizando classe oculta B const developer = person(‘developer’, 15); //Utilizando classe oculta B const conference = person(‘conference’, 15); //Criando e Utilizando classe oculta C developer.linguagem = “javascript”; Person Object Initial Hidden Class PA Initial Hidden Class PB Initial Hidden Class P0
  36. function person (name, age ) { //Criando classe oculta A

    this.name = name; //Criando classe oculta B this.age = age; } //Utilizando classe oculta B const developer = person(‘developer’, 15); //Utilizando classe oculta B const conference = person(‘conference’, 15); //Criando e Utilizando classe oculta C developer.linguagem = “javascript”; Person Object Initial Hidden Class PA Initial Hidden Class PB Initial Hidden Class P0
  37. function person (name, age ) { //Criando classe oculta A

    this.name = name; //Criando classe oculta B this.age = age; } //Utilizando classe oculta B const developer = person(‘developer’, 15); //Utilizando classe oculta B const conference = person(‘conference’, 15); //Criando e Utilizando classe oculta C developer.linguagem = “javascript”; Person Object Initial Hidden Class PB Initial Hidden Class PC Initial Hidden Class PA Initial Hidden Class P0
  38. Quanto mais previsíveis são os objetos menos classes ocultas serão

    criadas Daniel Clifford Manager and Tech Lead V8 Team, Google Chrome
  39. Pipeline de compilação (2010) Full- Codegen Código Não Otimizado Crankshaft

    Código otimizado Parser AST JavaScript Otimização Baseline Referência: TurboFan: A new code generation architecture for V8
  40. TurboFan • Iniciado em 2013 • Feito para otimizar as

    novas features do ES6 • Otimização mais sustentável e extensível para todas as arquiteturas • O Turbofan adicionou uma fase explícita de compilação de seleção de instruções que permite escrever muito menos codigo específico para cada arquitetura
  41. Full- Codegen Código Não otimizado Crankshaft Código otimizado TurboFan Parser

    AST JavaScript Otimização Baseline Referência: TurboFan: A new code generation architecture for V8 Pipeline de compilação (2014)
  42. V8 - Ignition • Redução do consumo de memória dos

    dispositivos móveis com 512mb-1g ram • Redução de memória • Redução do overhead do parse • Código 8x menor que o do Full-Codegen • Utiliza o Back-end do Turbofan
  43. Junção do Ignition + Turbofan • TurboFan e Ignition são

    utilizados na versão 5.9 do V8 • Menor consumo de memória • Preocupação em otimizar códigos (BlueBird, Babel e etc) • 20-35% mais rápido pelo Speedometer • No Node.js 10%+ performance
  44. Ignition Bytecode Código otimizado TurboFan Parser AST JavaScript Otimização Interpretador

    Referência: TurboFan: A new code generation architecture for V8 Pipeline de compilação (2017)
  45. Child Process • Node foi desenvolvimento para processos que necessitam

    de muito I/O • Pode ajudar a externalizar o uso intensivo de CPU da sua single Thread do Node.js
  46. Child Process • Deixa o event Loop do processo pai

    mais limpo • Cria um processo filho, ouve e controla • Exec() e Spawn() ◦ Exec executa em buffer ◦ Spawn cria um novo processo e retorna uma interface de stream pelo I/O
  47. • Uma única instância do node é executada numa single

    Thread • Uma das vantagens de ter um processador de múltiplos núcleos é que às vezes ele pode ser executado em clusters • O Node.js se encarrega de executar e balancear a carga para cada processo Cluster
  48. Referências Estrutura interna Node.js - https://nodejs.org/en/docs/meta/topics/dependencies/ Libuv - http://docs.libuv.org/en/v1.x/design.html Event

    Loop - http://latentflip.com/loupe/ - https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ - https://blog.risingstack.com/node-js-at-scale-understanding-node-js-event-loop/ - https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/ - http://walde.co/2016/11/27/node-js-o-que-e-esse-event-loop-afinal/ - https://www.youtube.com/watch?v=8aGhZQkoFbQ - https://www.youtube.com/watch?v=va8-xdxTywU
  49. Referências V8 - https://www.html5rocks.com/en/tutorials/speed/v8/ - http://developers.scup.com/otimizando-seu-javascript-no-v8-node-js/ - https://github.com/v8/v8/wiki/Design%20Elements - https://www.youtube.com/watch?v=UJPdhx5zTaw

    - Turbofan - https://www.youtube.com/watch?v=M1FBosB5tjM Child Process - https://nodejs.org/api/child_process.html Cluster - https://nodejs.org/api/cluster.html - http://rowanmanning.com/posts/node-cluster-and-express/
  50. Centro Av. Presidente Wilson, 231 - 29º andar (21) 2240-2030

    Cidade Monções Av. Nações Unidas, 11.541 - 3º andar (11) 4119-0449 Savassi Av. Getúlio Vargas, 671 Sala 800 - 8º andar (31) 3360-8900 www.concrete.com.br Centro Av. Presidente Wilson, 231 - 29º andar (21) 2240-2030 Cidade Monções Av. Nações Unidas, 11.541 - 3º andar (11) 4119-0449 Savassi Av. Getúlio Vargas, 671 Sala 800 - 8º andar (31) 3360-8900 www.concrete.com.br