Vou colocar abaixo o que já descobri sobre como aumentar a performance de um javascript, tanto pela economia de memória, quanto pelo processamento.
MEMORY TUNNING
Intro
Assim como outras linguagens, o javascript também tem GC (garbage collector), isto é, objetos da memória que não possuem mais nenhuma referência são automaticamente limpos a cada X tempo (ou outro critério).Criei o hello world abaixo para vermos o GC em ação. No código abaixo, a variável item é limpa a cada execução do GC, já que acabou seu escopo. Ex: http://jsfiddle.net/44Jj2/21/
Isso gera o serrilhado abaixo na memória, pelo inspecionador do Chrome:function createItem() {
var item = new Array(99999);
return item;
}
var myGlobal;
window.setInterval(function() {
myGlobal = createItem();
}, 100);
Vejamos agora algumas dicas para melhor uso de memória.
Uso do VAR
Sempre use var ao declarar uma variável (a menos que queira uma global). Se não fizer isso, ela será global e variáveis globais não podem ser limpas pelo GC pq ainda podem ser úteis para algo. Os prints abaixo mostram o consumo de memória para o script abaixo. No segundo eu troquei var item = bigSize(); por item = bigSize();.function createItem() {
var item = bigSize();
return item;
}
function bigSize() {
var a = new Array(9999);
for (var i = 0; i < a.length; i++) {
a[i] = new Array(999);
}
return a;
}
var myGlobal;
window.setTimeout(function(){
myGlobal = createItem();
myGlobal = null;
},1000);
Uso do DELETE
As implementações de js atuais (2012) não permitem que chamemos o método gc() diretamente no nosso código, então temos que esperar o gc() rodar. Porém, dependendo do uso de memória que nosso código faz, torna-se útil remover objetos da memória o quanto antes.Para isso, usa-se o delete.
(eu ia colocar um exemplo disso funcionando, mas nenhum dos testes que fiz conseguir ver diferença no serrilhado.)
Uso do PROTOTYPE
Usar o prototype para adicionar métodos a uma classe pode economizar muita memória, se houverem muitas instancias dessa classe. Pelos meus testes, o uso de memória caiu de 60MB para 21MB, no código abaixo. Observe que o método come() é criado direto na classe, o que gasta memória, já que a função será armazenada em cada uma das 500k instancias criadas. Já usando prototype, que está comentado abaixo, a função só fica armazenada em um local, na classe Pessoa.
var start = new Date().getTime();
var end;
var pessoas = [];
var interval = setInterval(function(){
for(var i = 0; i< 1000; i++) run();
},0)
function run(){
pessoas.push(new Pessoa());
var target = document.getElementById("target");
target.value = pessoas.length + " pessoas criadas";
if (pessoas.length > 500000) {
clearInterval(interval);
end = new Date().getTime();
target.value = pessoas.length + " pessoas criadas em " + (end - start) + "ms";
pessoas[0].come();
}
}
function Pessoa(){
this.nome = "XXXXXXXXXXXXXXXXXXXX";
this.come = function(){console.log("comendo...");} // comentar para testar
}
//Pessoa.prototype.come = function(){console.log("comendo...");} // descomentar para testar
<body>
<input type="text" value="" id="target" style="width: 500px;"/>
</body>
CPU TUNNING
Intro
Nos testes que fiz com o scrinux heat map descobri que é importante ter noção do gargalo antes de sair otimizando a torto e a direita. No início o problema era a parte gráfica. Após o uso do canvas, o gargalo passou a ser o processamento da matrix de pontos. Segue abaixo algumas descobertas.Ajuste de frames
Em animações/games é importante considerar algumas frequencias: a taxa de atualização do monitor (60Hz), a taxa de atualização do canvas e a taxa de processamento dos dados, que no meu caso era uma matrix de pontos, cada um com uma cor. Nao adianta atualizar o canvas a 100Hz (100 vezes por segundo), se o monitor só exibe a cada 60Hz. Vai ser perda de processamento. Sobre a taxa de atualizacao dos dados, é melhor atualizar os dados varias vezes a cada atualizacao de tela, assim a simulação pode ser acelerada. Ex:- Monitor: 60Hz
- Canvas: 60Hz
- Dados: 120Hz
Menos interrupções, maior desempenho
Uma outra dica é acumular vários processamentos a cada interrupção. O código abaixo mostra a diferenca obtida quando se processa 1x, 10x e 100x a cada interrupcao. O tempo cai de 2135ms para 32ms.
var start = new Date().getTime();
var end;
var ciclos = 0;
var interval = setInterval(function(){
run();
//run(); // 501 ciclos processados em 2135ms
//for(var i = 0; i< 10; i++) run(); // 510 ciclos processados em 214ms
//for(var i = 0; i< 100; i++) run(); // 600 ciclos processados em 32ms
},0)
function run(){
ciclos++;
if (ciclos>500) {
clearInterval(interval);
end = new Date().getTime();
var target = document.getElementById("target");
target.value = ciclos + " ciclos processados em " + (end - start) + "ms";
}
}
WebWorkers
Pendente: aguardando tempo para documentar o que já descobri...Algoritmos Evolutivos para otimizar configuracao
MISC
Ao criar esse post percebi que é mais difícil do que parece fazer os testes e tirar o print do serrilhado. Isso pq:- Várias coisas afetam o debug do estado da memória. Enquanto eu testava pelo jsfiddle ou pela home do Chrome, os resultados ficavam estranhos. Ajudou bastante criar um index.html só pra isso.
- O algoritmo de GC do Chrome é complexo. Ele muda conforme a quantidade de memória já usada, por ex. O serrilhado abaixo mostra que o GC aumentou o limite max de memória no decorrer do tempo.
var myGlobal;
window.setInterval(test, 1);
function test() {
myGlobal = new Array(9999);
}
Hello, I enjoy reading all of your article. I wanted to write a little
ResponderExcluircomment to support you.
my homepage :: click-fest.com
Appreciate this post. Let me try it out.
ResponderExcluirmy web page: http://comodescargar.com/
It's actually very complex in this active life to listen news on Television, so I just use world wide web for that purpose, and obtain the most up-to-date information.
ResponderExcluirMy homepage electronic nicotine
Excellent post. Keep writing such kind of info on your blog.
ResponderExcluirIm really impressed by your site.
Hello there, You've done an excellent job. I will certainly digg it and in my opinion suggest to my friends. I'm confident they'll be benefited from this site.
Here is my page :: e-cig
I'm not sure where you are getting your information, but good topic. I needs to spend some time learning more or understanding more. Thanks for great info I was looking for this info for my mission.
ResponderExcluirHere is my page ... e-cig