Como o Chrome V8 funciona? E por que o JavaScript não foi compilado por JIT?


19

Pesquisei Intérpretes / Compiladores, depois me deparei com o JIT-Compilation - especificamente o V8 Javascript Engine do Google Chrome.

Minhas perguntas são -

  1. Como pode ser mais rápido que a Interpretação padrão?
  2. Por que o JIT-Compilation não foi usado em primeiro lugar?


Meu entendimento atual

  1. Todo programa Javascript começa como código-fonte e, independentemente do método de execução, é traduzido para o código da máquina .
    Tanto a compilação de JIT quanto a interpretação devem seguir esse caminho; portanto, como a compilação de JIT pode ser mais rápida (também porque o JIT é com tempo limitado, diferentemente da compilação de AOT)?

  2. Parece que a compilação JIT é uma inovação relativamente antiga , baseada no artigo de compilação JIT da Wikipedia .

"O primeiro compilador JIT publicado é geralmente atribuído ao trabalho no LISP por McCarthy em 1960 ".

"Smalltalk (c. 1983 ) foi pioneiro em novos aspectos das compilações JIT. Por exemplo, a tradução para código de máquina foi feita sob demanda e o resultado foi armazenado em cache para uso posterior. Quando a memória se tornasse escassa, o sistema excluiria parte desse código e regeneraria quando era necessário novamente. "

Então, por que o Javascript foi interpretado para começar ?


Estou muito confuso e pesquisei bastante sobre isso, mas não encontrei respostas satisfatórias.

Respostas tão claras e concisas seriam apreciadas. E se uma explicação adicional sobre intérpretes, compiladores JIT, etc. precisar ser trazida, isso também será apreciado.


2
Os números 2 e 3 são responsáveis, mas "Como funciona o mecanismo Chrome V8?" sem nenhuma qualificação é muito amplo; a única resposta correta é um link para o código-fonte V8. Você queria perguntar algo mais específico sobre o V8? (se não seria melhor para remover essa parte da pergunta)
Ixrec

À segunda vista, o único ponto de eu pedir o número 1 era entender o número 2, então eu o removerei. Obrigado pela contribuição.
Anton Paras

Isso não é mencionado nas outras respostas, mas a compilação do JIT é difícil. Não é uma coisa simples de fazer, porque os erros resultantes da compilação JIT resultam em segfaults em vez de erros - o programa trava em vez de gerar um erro no console. Sim, para um programador C competente, confortável com o gdb, isso não é um problema. Mas quase todo programador C competente, confortável com o gdb, é pago para trabalhar em outros projetos. Algumas outras linguagens como Perl e Ruby ainda não têm intérpretes JIT convencionais.
Slebetman 13/11/2015

Caso você esteja se perguntando. Estou falando sobre isso da perspectiva de um desenvolvedor / mantenedor principal de uma linguagem de programação. Por alguns anos, fui contratado para manter a linguagem de programação Ferite. Uma das listas de desejos que tínhamos era implementar um JIT. Isso nunca aconteceu - nós mudamos para ir. O PHP só recentemente conseguiu um compilador JIT (HVVM), graças ao Facebook investindo dinheiro suficiente nele para que isso aconteça.
Slebetman

Respostas:


43

A resposta curta é que o JIT tem tempos de inicialização mais longos, mas é muito mais rápido a longo prazo, e o JavaScript não foi originalmente destinado a longo prazo.

Nos anos 90, o JavaScript típico em um site representaria uma ou duas funções no cabeçalho e um punhado de código incorporado diretamente nas onclickpropriedades e afins. Normalmente, ele é executado corretamente quando o usuário espera um grande atraso no carregamento da página. Pense na validação de formulários extremamente básica ou em pequenos utilitários matemáticos, como calculadoras de juros de hipotecas.

Interpretar conforme necessário foi muito mais simples e forneceu um desempenho perfeitamente adequado para os casos de uso do dia. Se você queria algo com desempenho de longo prazo, usava o flash ou um applet java.

O Google Maps em 2004 foi um dos primeiros aplicativos matadores para uso pesado de JavaScript. Foi revelador das possibilidades do JavaScript, mas também destacou seus problemas de desempenho. O Google passou algum tempo tentando incentivar os navegadores a melhorar seu desempenho em JavaScript e, finalmente, decidiu que a competição seria o melhor motivador e também daria a eles o melhor lugar na tabela de padrões do navegador. Chrome e V8 foram lançados em 2008 como resultado. Agora, 11 anos após o Google Maps entrar em cena, temos novos desenvolvedores que não se lembram que o JavaScript já foi considerado inadequado para esse tipo de tarefa.

Digamos que você tenha uma função animateDraggedMap. Pode demorar 500 ms para interpretá-lo e 700 ms para JIT compilá-lo. No entanto, após a compilação do JIT, pode levar apenas 100 ms para ser executado. Se for os anos 90 e você só chamar uma função uma vez e depois recarregar a página, o JIT não vale a pena. Se é hoje e você está ligando animateDraggedMapcentenas ou milhares de vezes, esses 200 ms extras na inicialização não são nada, e isso pode ser feito nos bastidores antes que o usuário tente arrastar o mapa.


2

Com a compreensão do que está acontecendo no tempo de execução, é possível fazer alterações no código ou na interpretação do código que permite que ele seja executado mais rapidamente ou compilado melhor do que o que é conhecido no tempo de compilação antecipado.

Muito pode ser dito sobre isso - é o assunto de grandes quantidades de pesquisa. Minha própria explicação aqui de que comecei a escrever empalidece em comparação com a resposta dada em Entendendo as diferenças: intérprete tradicional, compilador JIT, intérprete JIT e compilador AOT


Simplesmente, o JavaScript não foi inicialmente compilado ou analisado para o JIT porque nunca foi concebido para ser algo tão complexo ou importante.

A intenção original do Java Script era vincular aos applets Java em uma página da web. A capacidade de clicar em algum botão ou inserir um valor em um campo de formulário e, em seguida, funcionar em um método de applet Java pode ser vista em Invocando métodos de applet a partir do código JavaScript . Também foi possível, através do JavaScript, seguir o outro caminho de invocar o código JavaScript a partir de um applet .

A intenção original do JavaScript era vincular os applets e as páginas html que os continham. Para uma tarefa tão pequena, não é necessário um ótimo desempenho (se você quiser desempenho, chame o método de applet que é JIT'ed).

Somente depois que a Netscape começou a fazer um trabalho significativo com o JavaScript como seu próprio idioma e promovê-lo para o desenvolvimento (incluindo o JavaScript do lado do servidor no Netscape Enterprise Server - que, aliás, fez a compilação antecipada), o JavaScript veio à tona como um alvo sério . Depois de muitos anos, foram necessárias as ferramentas necessárias para torná-lo útil.


1
Não, o Javascript não está relacionado ao Java. E os applets Java são bytecode da JVM.
Basile Starynkevitch 30/07/2015

O JavaScript do @BasileStarynkevitch foi projetado para trabalhar com miniaplicativos Java em páginas hamlet - agindo como a cola entre o html dom e os métodos contidos nos objetos Java. Não é e nunca foi concebido para ser Java.

O JavaScript foi originalmente chamado de ECMAScript (ou algo parecido) e não tinha nada a ver com Java. Como se chama JavaScript é objeto de pesquisas separadas para os interessados. Isso causou confusão desde sempre.
quickly_now

1
@quickly_now e ainda é tc39.github.io/ecma262
caub:

Sim. E por alguma estranha razão, quando eu apontei isso acima, fui votado por isso!
quickly_now

1

JITs são rápidos para JavaScript, porque é impossível gerar código de máquina rápido quando você não conhece o tipo de suas variáveis.

Quando você não possui informações de tipo, os cálculos são caros. Por exemplo,

x + y

é bastante complicado se você não souber nada sobre x e y. Eles podem ser números inteiros, duplos, seqüências de caracteres ou até objetos nos quais esse cálculo tem efeitos colaterais. Como não temos digitação estática, esse é um cálculo caro.

Com a compilação just-in-time, podemos usar informações de tempo de execução e transformá-las em um cálculo mais rápido. No tempo de execução, o V8 controla o tipo de variáveis. Se o código acima for executado várias vezes com, digamos, strings, o compilador poderá executar instruções muito mais simples para a concatenação de strings. Portanto, quando o compilador alcança x + y, em vez de executar muitos códigos que se ramificam para muitos tipos diferentes de xey, o compilador rapidamente verifica se temos as strings novamente e, em seguida, executa apenas algumas linhas de código de máquina que concatenam as strings.

Por exemplo, em C ++, o compilador conhece os tipos de xey com antecedência, pois tivemos que declarar as variáveis. Portanto, ele pode gerar código de máquina otimizado para concatenar seqüências de caracteres antes de executar o código.


0

1) Como pode ser mais rápido que a Interpretação padrão? Bem, um exemplo pensado seria o seguinte; suponha que tenhamos 2 aplicativos ApplicationCompiled e ApplicationInterpreted. Ambos os programas fazem exatamente a mesma coisa e compartilham o mesmo código fonte. ApplicationCompiled leva 6 segundos para compilar.

Digamos que os horários do cenário A sejam:

  • Para ApplicationCompiled: 4 segundos
  • Para ApplicationInterpreted: 12 segundos

Portanto, no total ApplicationCompiled leva 10 segundos para executar o Cenário A (compilação de 6 segundos, 4 segundos em execução) e ApplicationInterpreted leva 12 segundos no total para executar. Não tenho um exemplo específico para lhe mostrar e não tenho certeza em quais casos os itens acima seriam verdadeiros - isso também depende muito de quão inteligentes são a interpretação e o compilador.

Obviamente, isso é muito simplificado, mas a mesma idéia pode ser aplicada à compilação / interpretação do JIT. A próxima pergunta seria "como determinamos - com baixo custo - se esse ramo deve ser compilado ou interpretado pelo JIT"? Estou fora da minha liga aqui :)

2) Por que o JIT-Compilation não foi usado em primeiro lugar? Não sei, mas reconheço que é simplesmente uma questão de recursos e maturidade do progresso disponível para tornar uma linguagem difícil de otimizar, como o JavaScript, aplicar técnicas avançadas como essas. Provavelmente havia muitas frutas mais baixas na época.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.