ti-enxame.com

Por que o JavaScript não é compilado no bytecode antes de enviar pela rede?

Você costuma ver que JavaScript está sendo transportado pela Web com todo o material inútil que não precisa estar lá - Comentários, particularmente aqueles que contêm licenças, recuos ( '\ t' , '\ n' ), etc. Com tempo suficiente, isso pode acabar desperdiçando terabytes de dados em todo o mundo! Um bytecode JavaScript causaria outro problema maior ou ninguém pensou nisso ainda?

155
Vivek Yadav

Por que o JavaScript não é compilado no bytecode antes de enviar pela rede?

Histórico: Eu participei do comitê técnico do ECMAScript no final dos anos 90 e um dos implementadores do mecanismo JScript da Microsoft.

Deixe-me começar dizendo o que sempre digo quando confrontado com um "por que não?" pergunta: os designers de idiomas não precisam dar boas razões para não gastar centenas de milhões de dólares de outras pessoas em um recurso que alguém gosta. Em vez disso, é necessário que a pessoa que apresenta o recurso forneça boas razões pelas quais essa é a melhor maneira de gastar esse tempo, esforço e dinheiro. Você argumentou sem números anexos que o bytecode seria uma economia de custos em termos de largura de banda. Gostaria de encorajá-lo a elaborar alguns números reais e comparar isso com os custos da criação de outro idioma; esses custos são significativos. Lembre-se de sua análise que "implementação" é um dos menores custos. Também em sua análise, inclua quem economiza o dinheiro versus quem gasta o dinheiro , e você descobrirá que não é o pessoal que gasta o dinheiro que o economiza; os incentivos são importantes.

Dito isto, este é um dos mais razoáveis ​​"por que não?" perguntas, porque é um recurso que consideramos e rejeitamos por razões.

Consideramos esse esquema, tanto na Microsoft quanto no nível do TC; como o JScript já foi implementado para compilar uma linguagem de código de código bem projetada e baseada em princípios, seria fácil propor isso como um padrão e consideramos fazê-lo.

Decidimos não, por vários motivos, incluindo:

  • Santo Deus, já era bastante difícil padronizar JavaScript . Todos e seus cães teriam uma opinião sobre quais eram as características ideais de uma linguagem de bytecode e seriam vários anos de prática de ciclismo. Ninguém realmente queria ir para lá.
  • Era uma solução cara, sem problemas caros associados. Não há razão para supor que uma linguagem de bytecode seja mais eficiente em tamanho ou velocidade. O JavaScript já minimiza razoavelmente bem e é altamente compactável.
  • Isso criaria uma enorme quantidade de trabalho para os provedores de navegadores, que já estavam irritados com a despesa de produzir uma implementação JS eficiente e compatível.
  • Criar uma implementação JS segura que resista a ataques de maus atores já é bastante difícil; devemos dobrar a superfície disponível para atacar? Provavelmente não.
  • Os padrões são um impedimento para a inovação. Se descobríssemos que uma pequena alteração em nossa linguagem de bytecode faria uma grande diferença em algumas coisas anteriormente imprevistas ou anteriormente sem importância cenário de usuário, estávamos livres para fazer essa alteração. Se fosse um padrão, não estaríamos livres para criar esse benefício para o usuário.

Mas essa análise pressupõe que o motivo para executar o recurso seja o desempenho. Curiosamente, as solicitações dos clientes que motivaram a consideração desse recurso na década de 1990 não eram principalmente sobre desempenho.

Por que não? A década de 1990 foi um período muito diferente para o JS do que hoje; os scripts eram minúsculos. A noção de que algum dia haveria estruturas com centenas de milhares de linhas não estava nem perto de estar no nosso radar. O download e a análise de JS foram uma pequena fração do tempo gasto no download e na análise de HTML.

A motivação também não foi a extensão para outros idiomas, embora isso tenha interesse para a Microsoft, pois tínhamos o VBScript em execução no navegador, que usava uma linguagem de código de código muito semelhante. (Sendo desenvolvido pela mesma equipe e compilado das mesmas fontes e tudo.)

Em vez disso, o cenário principal do cliente para motivar o bytecode no navegador era tornar o código mais difícil de ler, entender, descompilar, fazer engenharia reversa e adulterar. Que uma linguagem de bytecode dificilmente é um trabalho adicional a ser entendido por qualquer invasor com recursos razoáveis ​​foi o principal ponto contra esse trabalho; não queríamos criar uma falsa sensação de segurança.

Basicamente, havia muitas despesas e poucos benefícios preciosos, por isso não foi feito. Algo deve ter mudado entre 1998 e 2015 que fez o WebAssembly ter um preço razoável em benefício; quais são esses fatores, eu não sei. Você precisaria pedir a um especialista no WebAssembly.

381
Eric Lippert

Exibir fonte

"Exibir código-fonte" estava no começo e ainda é, até certo ponto, considerado um recurso importante da web. Foi assim que gerações de desenvolvedores da Web aprenderam o desenvolvimento da Web e os órgãos de padrões relevantes (ECMA TC39, W3C, WHATWG) ainda o levam muito a sério.

Minificação

Os arquivos ECMAScript geralmente são "minificados" antes de serem implantados. Isso inclui a remoção de todos os comentários, todos os espaços em branco e a renomeação de todos os identificadores para que sejam tão curtos quanto possível, além de algumas otimizações de nível superior, como a remoção de código morto.

Compressão

O suporte à compactação existe no HTTP desde HTTP/1.0 (início de 1996). ECMAScript é texto, e o texto é compactado muito bem. De fato, ECMAScript é um texto com muitas redundâncias (muitas aparências de ;, {, }, (, ), ,, ., function, var, if, for e assim por diante) e algoritmos de compactação prosperar em redundância. Portanto, a quantidade de dados transferidos é muito menor do que você imagina. Como um experimento, tente compactar um arquivo de origem ECMAScript com um dos algoritmos de compactação típicos usados ​​na Web (por exemplo, gzip ou deflate) e compare-o com o tamanho do bytecode compilado do mesmo arquivo.

Formato de bytecode

O que nos leva ao próximo problema: não há formato padronizado de bytecode para o ECMAscript. De fato, algumas implementações podem nem mesmo usar bytecode! Por exemplo, nos primeiros dois anos, o V8 compilou o ECMAScript diretamente para o código da máquina nativo, sem nenhuma etapa de bytecode no meio. Chakra, SquirrelFish Extreme e SpiderMonkey usam bytecode, mas eles usam bytecode diferente. dyn.js, TruffleJS, Nashorn e Rhine não usam o bytecode específico do ECMAScript, eles são compilados no bytecode da JVML. Da mesma forma, o IronJS compila no bytecode CLI CIL.

Agora, você pode dizer: por que não define um formato padronizado de bytecode para ECMAScript? Os problemas com isso são duplos:

  1. Um formato de bytecode restringe o design do mecanismo de execução. Por exemplo, observe as JVMs: as JVMs são muito mais semelhantes entre si do que os mecanismos ECMAScript. Pessoalmente, acredito que a "corrida de desempenho" do final dos anos 2000/início de 2010 não teria sido possível sem a ampla gama de experimentações oferecida pela falta de um formato padronizado de bytecode.

  2. Não é apenas difícil fazer com que todos os fornecedores de mecanismo ECMAScript concordem com um formato de bytecode padronizado comum, mas considere isso: não faz sentido adicionar um formato de bytecode para somente ECMAScript no navegador . Se você usa um formato de bytecode comum, seria bom se suportasse ActionScript, VBScript, Python, Ruby, Perl, Lua, PHP, etc. Mas agora você tem o mesmo problema do item 1, exceto o aumento exponencial: não apenas todos os fornecedores de mecanismos ECMAScript precisam concordar com um formato comum de bytecode, mas também o PHP, Perl, Ruby, Python, Lua, etc. comunidades a concordar também!

Armazenamento em cache

As bibliotecas amplamente conhecidas e conhecidas são hospedadas em URIs canônicos, onde podem ser referenciadas em vários sites. Portanto, eles só precisam ser baixados uma vez e podem ser armazenados em cache no lado do cliente.

CDN

Muitas bibliotecas usam CDNs, então elas são realmente servidas em um local próximo ao usuário.

Wasm/asm.js

WebAssembly (Wasm) é um formato de instrução binário compacto que atualmente está sendo padronizado pelo W3C e já está sendo enviado no Firefox, Chrome, Safari e Edge. No entanto, ele não foi projetado como formato de bytecode para o ECMAScript, mas como um código de máquina portátil de baixo nível e destino de compilação para idiomas como C, C++ e Rust.

Antes do Wasm, já havia o asm.js, que tinha objetivos semelhantes, mas ele foi projetado como um subconjunto sintático e semântico do ECMAScript, para que você pudesse executá-lo sem modificação em um mecanismo que não reconhece o asm.js e funcionaria, apenas muito mais lento.

114
Jörg W Mittag

O JavaScript foi inventado pela Netscape. O objetivo do design era tornar as páginas da web interativas por meio de uma linguagem de script incorporada. Inicialmente não era destinado a aplicativos complexos - coisas complexas deveriam ser escritas como Java applets ou plug-ins, e o JavaScript era posicionado como um simples código de "cola" que podia conectar elementos HTML com = Java applets e outros plug-ins com script.

O JavaScript foi projetado para ser incorporado diretamente no HTML, como <input type="button" onclick="alert('hello world')">. Hoje em dia, é desagradável incorporar JavaScript em HTML, mas naquela época era a maneira padrão de conectar manipuladores de eventos. Dado esse caso de uso, o JavaScript basicamente precisava ser baseado em texto.

Também havia recursos para gerar HTML em JavaScript, como:

<script>
  document.write("<input type=\"button\" onclick=\"alert('hello world')\">"
</script>

Novamente, isso basicamente requer que o JavaScript seja um formato de texto para ser útil.

Além disso, um formato de texto é muito mais fácil para desenvolvedores casuais, pois você não precisa de um ambiente de desenvolvimento para compilá-lo no código de bytes. Você acabou de digitar o texto e recarregar o navegador para vê-lo funcionar. No momento em que o JavaScript foi introduzido, quase não existiam editores dedicados em HTML. As pessoas escreviam páginas da web no bloco de notas. Não havia como construir pipelines para páginas da web.

As desvantagens que você mencionou não eram realmente uma consideração na época. Como foi projetado para pequenos scripts, a sobrecarga de um formato de texto era completamente insignificante.

18
JacquesB

O uso de dados provavelmente não é realmente um problema.

Responder à suposição no corpo (desde o maravilhoso resposta de Eric Lippert parece ter as perguntas reais muito bem cobertas):

Esteja você falando de limites de dados ou largura de banda, meu Google-Fu não conseguiu descobrir nenhuma pesquisa que sugira que o Javascript esteja realmente "desperdiçando terabytes de dados" (o que isso significa).

Quanto ao restante de suas perguntas, em muitas coisas, é menos útil perguntar "que problemas isso causará?" do que perguntar primeiro "que benefícios isso criará?".

1
sp88