Podemos fazer declarações gerais sobre o desempenho do código interpretado vs código compilado?

60

Estou comparando duas tecnologias para chegar a uma recomendação sobre qual delas deve ser usada por uma empresa. O código da tecnologia A é interpretado enquanto o código da tecnologia B é compilado para código de máquina. Na minha comparação, afirmo que a tecnologia B, em geral, teria melhor desempenho, uma vez que não tem a sobrecarga adicional do processo de interpretação. Também afirmo que, como um programa pode ser escrito de várias maneiras, ainda é possível que um programa escrito em tecnologia A supere um escrito em tecnologia B.

Quando submeti este relatório para revisão, o revisor declarou que não fornecia nenhuma razão clara para que, em geral, a sobrecarga do processo de interpretação fosse grande o suficiente para que pudéssemos concluir que o desempenho da tecnologia B seria melhor.

Então, minha pergunta é: podemos alguma vez dizer algo sobre o desempenho de tecnologias compiladas / interpretadas? Se podemos dizer compilado é geralmente mais rápido do que interpretado, como eu poderia convencer o revisor do meu ponto?

    
por EpicSam 10.01.2017 / 13:34
fonte

14 respostas

111

Não.

Em geral, o desempenho de uma implementação de idioma depende principalmente da quantidade de dinheiro, recursos, mão de obra, pesquisa, engenharia e desenvolvimento gasto nele.

E, especificamente, o desempenho de um determinado programa depende principalmente da quantidade de pensamento inserida em seus algoritmos.

Existem alguns muito interpretadores rápidos por aí, e alguns compiladores que geram código muito lento .

Por exemplo, uma das razões pelas quais Forth ainda é popular, é porque, em muitos casos, um programa interpretado por Forth é mais rápido do que o programa C compilado equivalente, enquanto, ao mesmo tempo, o programa do usuário escrito em Forth mais o interpretador Forth escrito em C é menor do que o programa do usuário escrito em C.

    
por 10.01.2017 / 14:07
fonte
81

Generalizações e cenários específicos são literalmente opostos.

Você parece estar se contradizendo. Por um lado, você quer fazer uma declaração geral sobre linguagens interpretadas vs compiladas. Mas, por outro lado, você deseja aplicar essa declaração geral a um cenário concreto envolvendo a Tecnologia A e a Tecnologia B.

Depois de aplicar algo a um cenário concreto, não é mais generalizado . Portanto, mesmo que você consiga argumentar que as linguagens interpretadas são mais lentas em geral , você ainda não está fazendo o que quer. Seu revisor não se importa com generalizações. Você está fazendo uma análise de duas tecnologias muito específicas. Isso é literalmente o oposto de generalizar.

    
por 10.01.2017 / 20:44
fonte
37

Como regra geral, um programa interpretado é cerca de 2x a 10x mais lento do que escrever o programa na linguagem de host do intérprete, com intérpretes para linguagens mais dinâmicas sendo mais lentas. Isso ocorre porque o programa interpretado tem que fazer todo o trabalho real, mas adicionalmente tem a sobrecarga de interpretação.

Dependendo da estrutura do intérprete, pode haver diferenças muito significativas. Há duas escolas contraditórias de design de intérprete: uma diz que os opcodes devem ser o mais pequenos possíveis para que possam ser otimizados com mais facilidade, o outro diz que os opcodes devem ser o maior possível para que possamos trabalhar mais dentro do intérprete. Quando a estrutura do seu programa coincide com a filosofia do intérprete, a sobrecarga se torna insignificante.

Por exemplo Perl é uma linguagem interpretada orientada para manipulação de texto. Um programa Perl idiomático fazendo manipulação de texto não será muito mais lento que um programa C, e pode até mesmo superar o programa C em alguns casos (possível porque Perl usa uma representação de string diferente e tem várias otimizações relacionadas a texto e IO). No entanto, fazer cálculos numéricos em Perl será insuportavelmente lento. Um incremento ++x é uma instrução de montagem única, mas envolve múltiplos percursos de ponteiro e ramificações para o interpretador Perl. Recentemente eu portei um script Perl ligado à CPU para C ++ e obtive um aumento de velocidade de 7x a 20x, dependendo do nível de otimização do compilador.

Falar sobre otimizações é importante aqui, já que um intérprete otimizado e polido pode superar um compilador ingênuo não otimizador. Como criar um compilador otimizado é difícil e requer muito esforço, é improvável que sua "tecnologia B" tenha esse nível de maturidade.

(Nota: a linguagem de programação O site Benchmarks Game tem uma estrutura confusa, mas quando você alcança a tabela de tempos para um problema, você notará que o desempenho de vários idiomas está em toda parte - muitas vezes, não há um limite claro de desempenho entre os dados compilados. e soluções interpretadas. A parte mais importante do site não é o resultado do benchmark, mas as discussões sobre como os benchmarks significativos são difíceis.)

Ao escolher uma tecnologia, o desempenho de um tempo de execução de linguagem em si é completamente irrelevante. É mais provável que seja importante que a tecnologia atenda a algumas restrições de linha de base (nosso orçamento é $ x, devemos ser capazes de entregar antes de aaaa-mm-dd, precisamos atender a vários requisitos não funcionais) e que ela tem um menor custo total de propriedade (fatoração na produtividade do desenvolvedor, custos de hardware, custos de oportunidade de negócios, risco de bugs e restrições inesperadas na tecnologia, custos de manutenção, treinamento e custos de contratação,…). Por exemplo. Em uma indústria em que o time-to-market é o fator mais importante, a tecnologia com a melhor produtividade do desenvolvedor seria a melhor opção. Para uma grande organização, a sustentabilidade e os custos a longo prazo podem ser mais interessantes.

    
por 10.01.2017 / 14:52
fonte
18

Você pode dizer algo sobre o desempenho de tecnologias compiladas / interpretadas. Mas primeiro, você deve definir "performance". Se você está construindo um sistema embarcado computacionalmente simples, então o "desempenho" provavelmente se inclinaria para o lado do uso de memória das coisas. Enquanto um sistema computacionalmente complexo operando em grandes conjuntos de dados se encontraria definindo o "desempenho" no número de cálculos por unidade de tempo, uma vez que a sobrecarga de memória da JVM ou da .NET seria insignificante.

Uma vez que você decide o que é "performance", pode dizer algo como "teremos 50 bilhões de objetos na memória a qualquer momento e o techA interpretado adiciona 8 bytes a cada objeto para gerenciamento interno, o que equivale a um Sobrecarga de memória de 400GB em comparação com o techB que não adiciona esses dados "

    
por 10.01.2017 / 14:02
fonte
12

Esta é uma questão técnica e você já tem muitas boas respostas técnicas, mas eu gostaria de apontar um aspecto ligeiramente diferente da sua situação: o fato de você não poder simplesmente basear uma decisão como "tecnologia A ou tecnologia B "puramente por razões técnicas e / ou de desempenho.

Os aspectos técnicos de algo como isso é apenas uma pequena parte da decisão entre A e B. Há dezenas de outros fatores para se ter em mente:

  • envolve custos de licenciamento? Por exemplo: você precisa pagar (uma quantia substancial) para usar um cluster de máquinas do SQL Server em vez de usar um cluster de máquinas PostgreSQL.
  • tenho funcionários familiarizados com essa tecnologia (pilha) e seu ecossistema? Se sim, eles estão disponíveis? Se não, posso contratar alguns? Quanto vai me custar? Ou eu treino os existentes? Quanto isso vai me custar?
  • o que o cliente quer? Isso pode ser um problema na maior parte do tempo.
  • a tecnologia que recomendo está pronta para uso em produção? Ou é apenas um hype atual que talvez acabe? (por exemplo, pense no Node.js quando ele foi lançado)
  • A tecnologia que eu recomendo se encaixa bem com a arquitetura existente ou a arquitetura que eu tinha em mente? Ou eu tenho que gastar muito dinheiro fazendo-os trabalhar juntos sem problemas?
  • e muitos outros aspectos que dependem da sua situação específica.

Como você pode ver, há uma tonelada de coisas a serem consideradas ao tomar essa decisão.

Eu sei que isso não responde especificamente à sua pergunta, mas eu acho que traz uma visão mais ampla sobre a sua situação e os detalhes de tal decisão.

    
por 11.01.2017 / 13:16
fonte
10

Avaliação parcial é uma estrutura conceitual relevante para relacionar intérpretes e compiladores.

Can we make general statements about the performance of interpreted code vs compiled code?

Linguagens de programação são especificações (escritas em alguns relatórios, como R5RS ou n1570 ). Eles não são software, então não faz sentido falar em performance . Mas algumas linguagens de programação podem ter várias implementações, incluindo intérpretes e compiladores .

Mesmo em linguagens tradicionalmente compiladas (isto é, linguagens cujas implementações são frequentemente compiladoras) como C, algumas partes são freqüentemente interpretadas. Por exemplo, a string de controle de formato de printf (definida no padrão C) é frequentemente "interpretado" (pela biblioteca padrão C , que tem uma função printf usando técnicas de argumentos variáveis) mas alguns compiladores (incluindo GCC ) são capazes de limitar casos específicos - para otimizá-lo e "compilá-lo" em chamadas de nível inferior.

E algumas implementações, mesmo dentro de "intérpretes", estão usando técnicas de compilação JIT (assim, gerar código em tempo de execução ). Um bom exemplo é luajit . Outras implementações (por exemplo, Python, Ocaml, Java, Parrot, Lua) estão traduzindo o código-fonte para um bytecode , que é então interpretado .

A SBCL é um "compilador" Common Lisp que traduz dinamicamente cada REPL interação (e chamadas para eval etc ...) em código de máquina. Então você sente que é um intérprete. A maioria das implementações JavaScript nos navegadores (por exemplo, v8 ) usam técnicas de compilação JIT.

Em outras palavras, a diferença entre interpretadores e compiladores é muito difusa (na verdade existe um continuum entre ambos) e, praticamente falando, a maioria das implementações de linguagem de programação tem frequentemente um interpretador e um compilador ( pelo menos para codificar byte) faceta.

Uma implementação pode ser rápida ou lenta, independentemente de usar a maioria das técnicas do tipo "compilador" ou "intérprete".

Alguns traços de linguagem favorecem uma abordagem de interpretação (e só podem ser compilados de maneira eficiente por meio da análise programa completo ).

Para alguns tipos de problemas, vale a pena projetar o software com algumas abordagens de metaprogramação dá importantes acelerações. Você poderia imaginar que, dada alguma entrada específica, seu programa dinamicamente gera código especializado para processá-lo. Isso é possível possível com C ou C ++ (usando alguma biblioteca JIT ou gerando algum código C, compilando-o como um plugin que é carregado dinamicamente).

Consulte também esta questão relacionada sobre o Python e que

    
por 11.01.2017 / 09:31
fonte
7

Para código como A = A + B , que pode compilar até uma ou duas instruções de máquina, cada uma tomando um certo número de ciclos. Nenhum intérprete pode fazer a mesma coisa nesse número de ciclos por um motivo simples.

O interpretador também executa um conjunto de instruções próprio (chame-os de códigos de bytes, códigos-p, idioma intermediário, etc.). Cada vez que ele vê um byte-code como ADD, ele precisa procurar de alguma forma e desviar para o código que faz a adição.

A próxima hora que ele vê, tem que repetir essa pesquisa, a menos que tenha uma maneira de lembrar a consulta anterior. Se houver uma maneira de lembrar a consulta anterior, ela não será mais o que chamamos de "intérprete", mas sim um compilador just-in-time ou JITter.

Por outro lado ...

Para código como callSomeFunction( ... some args ...) , quantos ciclos são gastos entre inserir esse código e deixá-lo? Tudo depende do que acontece dentro de callSomeFunction . Poderia ser alguns, e poderia ser trilhões, mesmo se callSomeFunction fosse compilado. Se é muito, não faz sentido debater o custo de interpretação dessa linha de código - o dinheiro está em outro lugar.

Lembre-se de que os idiomas interpretados têm um valor próprio, como não há necessidade de compilá-los. (A "compilação" da sintaxe de superfície para códigos de bytes toma um tempo trivial. Tome R ou MATLAB, por exemplo.)

Além disso, há flexibilidade necessária para níveis inteligentes de programação. Na Sociedade da Mente de Minsky, Capítulo 6.4 B -Brains, Existem programas que lidam com o mundo, e há programas B que lidam com programas A, e pode haver outros níveis. Programas que escrevem e gerenciam outros programas podem ser mais facilmente executados em sistemas interpretativos.

Em Lisp, você pode escrever (+ A B) para adicionar A e B, mas uma vez escrito, você só tem a opção de executá-lo ou não. Você também pode escrever (eval (list '+ 'A 'B)) , que constrói o programa e, em seguida, o executa. Pode construir algo diferente.

O assunto do programa é outro programa . Isso é mais fácil de escrever em uma linguagem interpretada (embora, como aponta Jörg, versões mais recentes do Lisp, enquanto eles têm eval , compile-on-the-fly, então eles não têm a penalidade de velocidade de interpretação). / p>     

por 10.01.2017 / 14:38
fonte
5

Mais ou menos, depende, mas como regra geral, o ambiente compilado - seja através de JIT ou estaticamente compilado - será mais rápido para muitas tarefas de computação intensiva - assumindo por simplicidade a mesma linguagem.

Parte do motivo é que as linguagens interpretadas precisam ter um laço de loop de intérprete que leia uma instrução, selecione a ação apropriada para executá-la. No melhor dos casos, como interpretar o bytecode do Python ou do Java (como a JVM fez) ele tem uma sobrecarga de poucas instruções e atrapalhou o preditor de ramificação - sem o último, você pode esperar grandes penalidades devido a interpretações errôneas. Mesmo um JIT muito idiota deve acelerar isso significativamente.

Dito isto, a linguagem interpretada pode enganar. Por exemplo, o Matlab otimizou rotinas para multiplicação de matrizes e com poucas mudanças você pode obter código rodando na GPU (disclaimer: Eu trabalho para a nVidia - qualquer opinião expressa aqui é minha e não representa a visão do meu empregador). Dessa forma, você pode escrever código de nível superior curto e poderoso sem se preocupar com detalhes - alguém tomou cuidado com isso e dedicou tempo e recursos para otimizá-lo em linguagem de baixo nível. Não há nada herdado sobre isso e isso não impede, por exemplo, que o Matlab codifique o código JIT, mas muitas vezes não há razão alguma, pois a sobrecarga da chamada de rotina de alto nível é mínima em comparação com o tempo gasto nos de baixo nível.

TL; DR - os programas compilados têm enormes benefícios de desempenho em relação aos interpretados (para comparação comparativa, consulte PyPy Speed ). No entanto, a velocidade do executável é apenas parte do problema e pode não contribuir muito para a velocidade geral (se o tempo é gasto principalmente em bibliotecas). Também a implementação é importante.

    
por 11.01.2017 / 09:09
fonte
5

Sua suposição é bem fundamentada, embora seja uma suposição.

Não vou repassar os motivos pelos quais o código compilado deve ser mais rápido do que o código interpretado: se você souber como os computadores funcionam, isso será óbvio. A diferença pode ser ordens de grandeza para certos tipos de problema. Se o revisor discordar seriamente desse caso geral, ele não sabe do que está falando.

Onde eles podem ter um ponto, porém, é se a diferença é significativa no tipo de aplicativo que você está desenvolvendo. Se é principalmente I / O ou principalmente chamando bibliotecas compiladas e não tem muita computação, a sobrecarga do processo de interpretação pode de fato ser insignificante.

Mas o ponto do meu post é este: como um I.T. Especialista você será freqüentemente chamado para tomar decisões precipitadas com base em um conhecimento geral de como as coisas devem funcionar. Se você fizer um teste específico, poderá obter uma resposta mais precisa, mas custará muito mais e não chegará lá primeiro.

Mas de tempos em tempos você é pego. Isso aconteceu comigo. Você faz uma boa suposição e depois descobre que não levou em conta a estupidez do mundo.

Mas eu não posso explicar tão bem como o meu desenho favorito de Dilbert de todos os tempos. Nada mostra melhor do que isso os perigos de ser um espertinho.

TL; DR: você deve estar certo, mas verifique o mundo real apenas no caso.

    
por 13.01.2017 / 09:53
fonte
3

A menos que você use algo um pouco exótico, seu problema não será sobre o desempenho de uma linguagem interpretada A e da linguagem compilada B.

Porque se você / sua equipe conhece A e não B e assim escreve um código melhor em A que B, você pode acabar tendo um desempenho muito melhor em A que B. Se você tem pessoas com experiência em um idioma e idioma / bibliotecas pode fazer o trabalho que você precisa, cumpri-lo.

Aqui está um link sobre regex em vários idiomas; você verá que o regex é implementado melhor em alguma linguagem, mesmo se compilado ou não: link

    
por 10.01.2017 / 14:04
fonte
1

Acho que não é uma boa ideia falar sobre o desempenho de duas tecnologias apenas com base no fato de que uma é compilada e a outra é interpretada. Como afirmado em outras respostas, pode depender da área de aplicação (algumas linguagens podem ser otimizadas para fazer algumas operações muito rapidamente e fazer outras coisas mais lentamente), bem como na experiência de pessoas que estão prestes a usar essa tecnologia.

Eu não acho razoável esperar que você obtenha um aumento de desempenho se você pegar alguns excelentes codificadores de linguagem interpretados e dar a eles alguma tecnologia com a qual eles não estão familiarizados - talvez em teoria o último possa resultar em melhor desempenho, mas na realidade, sem as habilidades e a experiência necessárias, você não usará todas as oportunidades de otimização.

De um dos conhecidos funcionários da empresa do Vale do Silício, também ouvi dizer que eles preferem o idioma mais simples de usar, pois é mais caro e problemático pagar alguns desenvolvedores qualificados para manter um código complicado, mas altamente otimizado. do que apenas comprar mais equipamento para lidar com a implementação menos eficiente, de modo que também deve ser considerado na escolha da tecnologia.

    
por 11.01.2017 / 11:11
fonte
0

Uma vez eu tive que fazer uma declaração abrangente para justificar uma grande decisão.

Primeiro, eles podem não querer acreditar em um engenheiro humilde, então eu encontrei alguns testes de benchmark comparáveis e os citei. Há muitos deles, de pessoas como a Microsoft ou universidades renomadas. E eles dirão coisas como: O método A é entre 3 e 10 vezes mais rápido que o método B, dependendo das variáveis X e Y.

Em segundo lugar, você pode querer executar um benchmark, talvez usando um trecho representativo do código em questão, ou algo similar que você já tenha. Execute-o 1000 vezes durante a noite, de modo que realmente haja uma diferença mensurável.

Neste ponto, a diferença (ou falta dela) entre A e B deve ser tão clara que você só precisa apresentá-la. Portanto, formate os resultados claramente, com diagramas, se possível, declarando todas as suposições e definindo todos os dados usados.

    
por 12.01.2017 / 15:01
fonte
0

Eu diria que qualquer linguagem dinâmica tem uma vantagem sobre as compiladas estaticamente: "Otimizações em tempo de execução"

Essa é uma das razões pelas quais o Java pode ser mais rápido que o C ++

Sim, o carregamento de uma linguagem digitada dinamicamente sempre terá o custo da tradução e estará em desvantagem. Mas, uma vez em execução, o interpretador pode criar perfis e aprimorar caminhos de código frequentes com informações de tempo de execução que linguagens estáticas nunca terão

NOTA: Bem, Java é uma linguagem interpretada, não dinâmica. Mas é um ótimo exemplo do que você pode acelerar com informações de tempo de execução

    
por 14.01.2017 / 09:26
fonte
-3

... I also state that since a program could be written in many ways it is still possible a program written in tech A could outperform one written in tech B.

When I submitted this report for review, the reviewer stated that I offered no clear reason why in general the overhead of the interpretation process would be large enough that we could conclude that tech B's performance would be better. ...

Essa seria minha abordagem:

Em geral, os intérpretes são compilados, então toda tecnologia interpretada nada mais é do que uma tecnologia compilada se analisada em um nível baixo. Portanto, as tecnologias compiladas são mais e com mais possibilidades, você nunca pode ficar pior se você for inteligente (o que em geral você é). Depende de quanta informação existe disponível em tempo de compilação e quanta informação está disponível apenas em tempo de execução e quão bons são os compiladores e interpretadores, mas teoricamente sempre deve ser possível pelo menos igualar o desempenho de qualquer interpretador com um compilador adequado, só porque intérpretes são fabricados por compiladores. Isso é possível, não significa que seja o caso para os seus técnicos A e B.

Na prática, basta informar ao revisor sobre todos os benchmarks disponíveis onde os sistemas compilados e interpretados são comparados. Em seguida, peça-lhe para sugerir um intérprete que supere seu algoritmo específico codificado e otimizado para montagem.

Pode-se acrescentar, talvez, que qualquer afirmação geral não ajuda em nada ao comparar dois técnicos específicos A e B. A escolha de A e B é muito mais importante do que se fossem interpretados ou compilados. / p>     
por 12.01.2017 / 12:03
fonte