JavaScript – Por que optimizar?

Banner (1)

O JavaScript surgiu em 1996 no Netscape Navigator, num contexto onde otimização não era algo muito considerado pelos desenvolvedores, embora as páginas levassem bastante tempo para carregar.

Seu surgimento veio com o propósito de melhorar a experiência do usuário, realizando tarefas mais simples diretamente na página ao invés de utilizar o servidor para isso (imagina você preencher um formulário, esperar de 30s a 60s pra enviá-lo após submeter, e depois receber uma validação de que um campo não foi preenchido?! pois é!) Nessa época o JavaScript era utilizado meramente para enviar mensagens.

Com a chegada do Internet Explorer 4 (IE4) no mercado e o dynamic HTML (capacidade de alterar elementos das páginas sem precisar recarregá-las), a quantidade de JavaScript nelas só aumentou. Em seguida, veio a introdução do DOM (Document Object Model), que nada mais é do que uma abordagem unificada do DHTML que foi adotada pelo IE5, Netscape 6 e Opera, o que logo foi acompanhado pela padronização do JavaScript no ECMA-262 (3ª edição).

À medida em que estes progressos iam acontecendo, sistemas web mais complexos iam surgindo e aumentava a quantidade de código JavaScript nas suas páginas. O problema é que a engine do JavaScript ainda era a mesma de 1996, em que as páginas ainda não eram tão recheadas de JavaScript. Browsers como o IE6, que surgiu em 2001, tornaram-se mais lentos com o passar dos anos pois as páginas que iam surgindo utilizavam cada vez mais códigos JavaScript, e como a engine era muito antiga, não estava preparada. Em suma, explicando de forma um pouco mais técnica, ela trabalhava de forma a procurar um número fixo de objetos na memória para determinar quando deveria coletar o lixo. Nos primórdios, os desenvolvedores não atingiam este limite, mas com o aumento de código JavaScript nas páginas, a quantidade de objetos aumentou e aplicações mais complexas foram sendo desenvolvidas, então este limite passou a ser atingido com frequência, exigindo cada vez mais dos browsers.

Os desenvolvedores web evoluíram, mas as engines estavam paradas no tempo.

Embora os diferentes browsers da época tivessem lógicas diferentes (e até um pouco mais eficientes) para lidar com o problema da coleta de lixo, a maioria deles utilizava um interpretador JavaScript para executar o código. Como se sabe, a interpretação de código exige a tradução entre o código e as instruções do computador que devem ser executadas, o que é um processo bem mais lento, se comparado com a compilação.

Compiladores já funcionam diferente. Eles determinam a partir de uma análise léxica, o que o código está tentando fazer para então otimizá-lo produzindo um código mais rápido para a execução da tarefa.

Em 2008 o Google lançou o Chrome, o primeiro navegador com uma engine otimizadora de JavaScript, o V8, o qual faz a compilação ‘just-in-time‘ do JavaScript e é capaz de produzir código de máquina a partir de JavaScript e executá-lo, resultando na sua execução de forma bem mais performática. Seguindo essa ideia novas engines de JS vieram surgindo e com o passar dos anos evoluindo, como o Nitro do safari, o traceMonkey, JaegerMonkey, SpiderMonkey, etc..

Mesmo com estes avanços no tempo de execução no núcleo do JavaScript, ainda há situações que as engines modernas não conseguem resolver, como operações que afetam a aparência das páginas, atrasos provocados pela latência da rede, etc. Assim, o desenvolvedor JavaScript precisa buscar conhecimento para entender vários aspectos diferentes, como latência, bloqueio e downloads em paralelo, interação com o DOM, etc, preocupando-se sempre com a melhor forma de escrever seu código, para obter um melhor desempenho na execução de seu código, melhorando por consequência a experiência do usuário ao navegar nas páginas.