Slide 1

Slide 1 text

Deixando o V8 otimizar sua aplicação Node

Slide 2

Slide 2 text

Talysson / @talyssonoc talyssonoc.github.io Codeminer42

Slide 3

Slide 3 text

Node & V8

Slide 4

Slide 4 text

Node & V8 ● V8: máquina virtual JS ● Libuv: async I/O + =

Slide 5

Slide 5 text

V8 & Crankshaft Full compiler AST Código nativo CPU JS

Slide 6

Slide 6 text

V8 & Crankshaft Full compiler Crankshaft compiler AST CPU JS Código nativo otimizado Código nativo Código otimizável

Slide 7

Slide 7 text

V8 & Crankshaft Full compiler Crankshaft compiler AST Código nativo CPU JS Bail out Código otimizável Código nativo otimizado

Slide 8

Slide 8 text

Escrevendo código otimizável

Slide 9

Slide 9 text

1) Atribuição em argumento function mySlowFunction(a, b) { if(arguments.length < 2) { b = 5; } }

Slide 10

Slide 10 text

function myFastFunction(a, _b) { var b = _b; if(arguments.length < 2) { b = 5; } } 1) Atribuição em argumento function mySlowFunction(a, b) { if(arguments.length < 2) { b = 5; } }

Slide 11

Slide 11 text

var args = [].slice.call(arguments); 2) Vazamento do arguments function leaksArguments() { return arguments; }

Slide 12

Slide 12 text

var args = new Array(arguments.length); for(var i = 0; i < args.length; ++i) { args[i] = arguments[i]; } * Uso seguro do arguments arguments.length; arguments[i]; // `i` válido fn.apply(y, arguments); // único

Slide 13

Slide 13 text

3) For-in em objetos em hash table mode var hashTable = { 'invalid-identifier': 3, 123: 'not cool' validIdentifier: 'cool' }; delete hashTable.validIdentifier; for(var key in hashTable) { console.log('I am slow!'); }

Slide 14

Slide 14 text

var hashTable = { 'invalid-identifier': 3, validIdentifier: 'cool' }; delete hashTable.validIdentifier; var keys = Object.keys(hashTable); keys.forEach(function(key) { console.log('I am fast!!'); }); 3) For-in em objetos em hash table mode var hashTable = { 'invalid-identifier': 3, 123: 'not cool' validIdentifier: 'cool' }; delete hashTable.validIdentifier; for(var key in hashTable) { console.log('I am slow!'); }

Slide 15

Slide 15 text

var key; function nonLocalKey2() { var obj = {}; for(key in obj); } function nonLocalKey1() { var obj = {}; for(var key in obj); return function() { return key; }; } 4) For-in com chave não local

Slide 16

Slide 16 text

var array = [1, 2, 3]; for(var i in array) { console.log(array[i]); } 5) For-in em objetos com índices numéricos

Slide 17

Slide 17 text

var array = [1, 2, 3]; for(var i in array) { console.log(array[i]); } 5) For-in em objetos com índices numéricos var array = [1, 2, 3]; var length = array.length; for(var i = 0; i < length; i++) { console.log(array[i]); } array.forEach((v) => { console.log(v); });

Slide 18

Slide 18 text

6) try/catch e try/finally function slowTryCatch() { try { for(var i = 0; i++; i < 1000) { console.log(i * i * i); } } catch(e) { console.log(e); } }

Slide 19

Slide 19 text

function fastTryCatch() { try { doSomethingHeavy(); } catch(e) { console.log(e); } } 6) try/catch e try/finally function slowTryCatch() { try { for(var i = 0; i++; i < 1000) { console.log(i * i * i); } } catch(e) { console.log(e); } }

Slide 20

Slide 20 text

7) Parâmetro de tipo não esperado var obj = { prop1: 1 }; function test(param) { param.prop2 = 2; // não tem `prop2` } test(obj);

Slide 21

Slide 21 text

var obj = { prop1: 1, prop2: null }; function test(param) { param.prop2 = 2; // tem `prop2` } test(obj); 7) Parâmetro de tipo não esperado var obj = { prop1: 1 }; function test(param) { param.prop2 = 2; // não tem `prop2` } test(obj);

Slide 22

Slide 22 text

8) Funções com argumentos variáveis function calc() { if(arguments.length === 2) { return arguments[0] * arguments[1]; } return arguments[0]; }

Slide 23

Slide 23 text

function calc() { if(arguments.length === 2) { return calcTwo(arguments[0], arguments[1]); } return calcOne(arguments[0]); } function calcOne(a) { return a } function calcTwo(a, b) { return a * b } 8) Funções com argumentos variáveis function calc() { if(arguments.length === 2) { return arguments[0] * arguments[1]; } return arguments[0]; }

Slide 24

Slide 24 text

9) Uso de debugger function fnWithDebugger() { if(process.env.NODE_ENV === 'dev') { debugger; } } function fnWithDebugger() { if(false) { debugger; } }

Slide 25

Slide 25 text

function fnWithEval(param) { return; eval(`this.alert(${param})`); } 10) Uso de eval() function fnWithEval(param) { eval(`this.alert(${param})`); }

Slide 26

Slide 26 text

function * generator1(param) { var something = 0; for(var i = 0; i < 1000; i++) { something += i; } yield something; } 11) Generators function * generator2(param) { for(var i = 0; i < 1000; i++) { yield i; } }

Slide 27

Slide 27 text

for(var item of array) { console.log(item); } 12) Uso de for-of

Slide 28

Slide 28 text

for(var item of array) { console.log(item); } 12) Uso de for-of var length = array.length; for(var i = 0; i < length; i++) { console.log(array[i]); } array.forEach((item) => { console.log(item); });

Slide 29

Slide 29 text

Entre outros ● Objetos com __proto__ ● Objetos com set / get ● Funções muito grandes ● Uso do with ● Índice negativo em arrays ● Nome de propriedade computada ● Otimização falhou muitas vezes ● Uso do super ● ...

Slide 30

Slide 30 text

Mas isso funciona mesmo?!

Slide 31

Slide 31 text

Exemplos de resultados Bluebird EventEmitter2

Slide 32

Slide 32 text

O futuro do V8: TurboFan

Slide 33

Slide 33 text

TurboFan ● Novo JIT do V8 ● Trabalha após o Crankshaft ● Otimizações mais sofisticadas ● Eventualmente substituirá o Crankshaft TurboFan no Chrome 41

Slide 34

Slide 34 text

Referências ● Optimization killers: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers ● V8 bailout reasons: https://github.com/vhf/v8-bailout-reasons ● NodeJS Anti-Patterns: https://github.com/zhangchiqing/OptimizationKillers ● A tour of V8: Crankshaft, the optimizing compiler: http://jayconrod.com/posts/54/a-tour- of-v8-crankshaft-the-optimizing-compiler ● Bailout reasons: https://cs.chromium.org/chromium/src/v8/src/bailout-reason.h ● TurboFan: http://v8project.blogspot.com.br/2015/07/digging-into-turbofan-jit.html ● TurboFan performance: http://blog.chromium.org/2015/07/revving-up-javascript- performance-with.html

Slide 35

Slide 35 text

Talysson / @talyssonoc talyssonoc.github.io