Desenvolvimento

9 mar, 2015

O Promise.prototype.then é o mais rápido “nextTick”?

Publicidade

Recentemente, passei alguns dias otimizando o desempenho de inicialização de um aplicativo web do Firefox OS. Ao analisar os dados do perfil e da linha do tempo, percebi que a “mensagem” DOMEvent estava provocando um atraso considerável – Essa “mensagem” é, na verdade, baseada na função setZeroTimeout do David Baron, que é usada algumas vezes ao longo da base de código. Então, eu tive a ideia de usar um Promise resolvido e verificar se ele mudaria alguma coisa, e fiquei impressionado com os ganhos de desempenho! Então, decidi pesquisar se alguém encontrou os mesmos resultados, mas não consegui achar nada e resolvi escrever este artigo.

O Promise.prototype.then chama o callback durante a fila microtask que acontece no final do loop de execução…

Promise.resolve().then(() => console.log('log: 1'));
console.log('log: 2');
// > "log: 2"
// > "log: 1"

Então, isso significa que o callback provavelmente acontecerá antes que qualquer paint/reflow/style possa ser desencadeado durante esse loop (a menos que você force um refluxo…), de modo que essa é a principal razão pela qual ele melhorou o desempenho do meu app, que basicamente empacotou todos os refluxos e a execução de código, reduzindo o trashing do layout e fazendo mais coisas em paralelo, além do fato de que ele executa muito mais rápido do que o window.postMessage.

Aqui está o código extremamente simples:

// insanely fast nextTick for browsers that support native Promises!
var resolved = Promise.resolve();
module.exports = function nextTick(fn) {
  resolved.then(fn);
};

Se você quiser comparar com outras soluções malucas, consulte este teste jsperf.

Eu não testei o uso de memória – teoricamente, vai causar mais coleta de lixo, uma vez que Promise#then retorna um novo objeto Promise em cada chamada; mas os ganhos de desempenho e a quantidade de chamadas nextTick que tenho (menos de 10 chamadas durante a inicialização) deveriam tornar isso irrelevante.

Eu não tenho certeza se é uma boa ideia ou não, mas sei que melhorou a inicialização do meu aplicativo e as coisas ainda funcionam, por isso é bom o suficiente para mim.

“A melhor maneira de obter a resposta certa na Internet não é fazer uma pergunta, é postar a resposta errada” – Lei de Cunningham

PS: Eu estou tentando fazer um carregamento complexo de app web abaixo de 1s em um dispositivo móvel low-end; em um navegador de desktop, a diferença de desempenho é insignificante na maioria dos casos. (Essa mudança só me economizou ~ 80ms).

PPS: Para entender o porquê, você pode precisar de uma função nextTick. consulte a documentação do Node.js.

***

Miller Medeiros faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://blog.millermedeiros.com/promise-nexttick/