View
140
Download
1
Category
Preview:
Citation preview
Deixando o V8 otimizar sua aplicação Node
Talysson / @talyssonoctalyssonoc.github.io Codeminer42
Node & V8
Node & V8
● V8: máquina virtual JS● Libuv: async I/O
+
=
V8 & Crankshaft
Fullcompiler
AST Código nativo
CPUJS
V8 & Crankshaft
Fullcompiler
Crankshaftcompiler
AST
CPUJS
Códigonativo
otimizado
Código nativo
Código otimizável
V8 & Crankshaft
Fullcompiler
Crankshaftcompiler
AST
Código nativo
CPUJS
Bail out
Código otimizável Códigonativo
otimizado
Escrevendo código otimizável
1) Atribuição em argumento
function mySlowFunction(a, b) {
if(arguments.length < 2) {
b = 5;
}
}
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;
}
}
var args = [].slice.call(arguments);
2) Vazamento do arguments
function leaksArguments() {
return arguments;
}
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
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!');
}
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!');
}
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
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];
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);
});
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);
}
}
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);
}
}
7) Parâmetro de tipo não esperado
var obj = { prop1: 1 };
function test(param) {
param.prop2 = 2; // não tem `prop2`
}
test(obj);
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);
8) Funções com argumentos variáveis
function calc() {
if(arguments.length === 2) {
return arguments[0] * arguments[1];
}
return arguments[0];
}
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];
}
9) Uso de debugger
function fnWithDebugger() {
if(process.env.NODE_ENV === 'dev') {
debugger;
}
}
function fnWithDebugger() {
if(false) {
debugger;
}
}
function fnWithEval(param) {
return;
eval(`this.alert(${param})`);
}
10) Uso de eval()
function fnWithEval(param) {
eval(`this.alert(${param})`);
}
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;
}
}
for(var item of array) {
console.log(item);
}
12) Uso de for-of
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);
});
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● ...
Mas isso funciona mesmo?!
Exemplos de resultados
Bluebird
EventEmitter2
O futuro do V8: TurboFan
TurboFan
● Novo JIT do V8● Trabalha após o
Crankshaft● Otimizações mais
sofisticadas● Eventualmente
substituirá o Crankshaft
TurboFan no Chrome 41
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
Talysson / @talyssonoctalyssonoc.github.io
Recommended