Estou comparando duas tecnologias para obter uma recomendação para qual delas deve ser usada por uma empresa. O código da tecnologia A é interpretado enquanto o código da tecnologia B é compilado no código da máquina. Na minha comparação, afirmo que a tecnologia B em geral teria melhor desempenho, pois não possui a sobrecarga adicional do processo de interpretação. Afirmo também que, como um programa pode ser escrito de várias maneiras, ainda é possível que um programa escrito na tecnologia A possa superar um programa escrito na tecnologia B.
Quando enviei este relatório para revisão, o revisor declarou que não ofereci uma razão clara para que, em geral, a sobrecarga do processo de interpretação fosse grande o suficiente para concluirmos que o desempenho da tecnologia B seria melhor.
Então, minha pergunta é: podemos dizer algo sobre o desempenho de tecnologias compiladas / interpretadas? Se podemos dizer que compilado geralmente é mais rápido do que interpretado, como convencer o revisor do meu argumento?
Respostas:
Não.
Em geral, o desempenho de uma implementação de linguagem depende principalmente da quantidade de dinheiro, recursos, mão de obra, pesquisa, engenharia e desenvolvimento gastos nela.
E, especificamente, o desempenho de um programa em particular depende principalmente da quantidade de pensamento colocada em seus algoritmos.
Existem alguns intérpretes muito rápidos por aí e alguns compiladores que geram código muito lento .
Por exemplo, um dos motivos pelos quais a Forth ainda é popular é porque, em muitos casos, um programa Forth interpretado é mais rápido que o programa C compilado equivalente, enquanto, ao mesmo tempo, o programa do usuário escrito em Forth mais o intérprete Forth escrito em C é menor que o programa do usuário escrito em C.
fonte
Generalizações e cenários específicos são literalmente opostos.
Você parece estar se contradizendo. Por um lado, você deseja fazer uma declaração geral sobre linguagens interpretadas versus 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, ele não é mais generalizado . Portanto, mesmo se você puder argumentar que as linguagens interpretadas são mais lentas em geral , ainda não está fazendo o seu ponto. Seu revisor não se preocupa com generalizações. Você está fazendo uma análise de duas tecnologias muito específicas. Isso é literalmente o oposto de generalizar.
fonte
Como regra geral, um programa interpretado é cerca de 2x – 10x mais lento do que gravar o programa no idioma host do intérprete, sendo mais lentos os intérpretes para idiomas mais dinâmicos. Isso ocorre porque o programa interpretado precisa executar todo o trabalho real, mas também possui a sobrecarga de interpretação.
Dependendo da estrutura do intérprete, pode haver diferenças muito significativas. Existem duas escolas contraditórias de design de intérpretes: uma diz que os opcodes devem ser tão pequenos quanto possível, para que possam ser otimizados com mais facilidade; a outra diz que os opcodes devem ser o maior possível para que trabalhemos mais com o intérprete. Quando a estrutura do seu programa corresponde à filosofia do intérprete, a sobrecarga se torna insignificante.
Por exemplo, Perl é uma linguagem interpretada orientada para a manipulação de texto. Um programa Perl idiomático que manipula texto não será muito mais lento que um programa C e pode até superar o programa C em alguns casos (possível porque o Perl usa uma representação de string diferente e possui várias otimizações relacionadas a texto e IO incorporadas). No entanto, fazer trituração de números no Perl será insuportavelmente lento. Um incremento
++x
é uma única instrução de montagem, mas envolve várias passagens e ramificações do ponteiro para o interpretador Perl. Recentemente, eu movi um script Perl vinculado à CPU para C ++ e obtive uma aceleração de 7x a 20x, dependendo do nível de otimização do compilador.Falar sobre otimizações é importante aqui, pois um intérprete polido e otimizado pode superar razoavelmente o desempenho de um compilador ingênuo que não otimiza. Como a criação de um compilador otimizador é difícil e requer muito esforço, é improvável que sua "tecnologia B" tenha esse nível de maturidade.
(Observação: o site do jogo Computer Benchmarks de referência tem uma estrutura confusa, mas quando você chegar à tabela de horários para um problema, perceberá que o desempenho de vários idiomas está em todo lugar - geralmente, não há um limite de desempenho claro entre soluções compiladas e interpretadas. A parte mais importante do site não são os resultados de benchmark, mas as discussões sobre quão difíceis são os benchmarks significativos.)
Ao escolher uma tecnologia, o desempenho de um tempo de execução de linguagem é completamente irrelevante. É mais provável que seja importante que a tecnologia atenda a algumas restrições da linha de base (nosso orçamento é de $ x, devemos ser capazes de entregar antes de aaaa-mm-dd, devemos atender a vários requisitos não funcionais) e ter uma menor custo total de propriedade (considerando a produtividade do desenvolvedor, custos de hardware, custos de oportunidades de negócios, risco de erros e restrições inesperadas na tecnologia, custos de manutenção, custos de treinamento e contratação, ...). Por exemplo, em um setor em que o tempo de colocação no mercado é o fator mais importante, a tecnologia com a melhor produtividade do desenvolvedor seria a mais adequada. Para uma organização grande, a manutenção e os custos a longo prazo podem ser mais interessantes.
fonte
Você absolutamente pode dizer algo sobre o desempenho de tecnologias compiladas / interpretadas. Mas primeiro, você deve definir "desempenho". Se você estiver criando um sistema embarcado computacionalmente simples, o "desempenho" provavelmente se inclinará para o lado do uso da memória. Enquanto um sistema computacionalmente complexo operando em grandes conjuntos de dados se definiria "desempenho" no número de cálculos por unidade de tempo, uma vez que a sobrecarga de memória da JVM ou .NET seria insignificante.
Depois de decidir sobre o que é "desempenho", você pode dizer algo como "teremos 50 bilhões de objetos na memória a qualquer momento e a tecnologia interpretada adiciona 8 bytes adicionais a cada objeto para gerenciamento interno, o que equivale a uma sobrecarga de memória de 400 GB em comparação com o techB, que não adiciona esses dados "
fonte
Esta é uma pergunta técnica e você já tem muitas respostas técnicas boas, mas gostaria de destacar um aspecto um pouco diferente da sua situação: o fato de você não poder basear apenas 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 assim são apenas uma pequena parte da decisão entre A e B. Há dezenas de outros fatores a serem lembrados:
Como você pode ver, há MUITAS coisas a considerar ao tomar essa decisão.
Sei que isso não responde especificamente à sua pergunta, mas acho que traz uma visão mais ampla da sua situação e dos detalhes de tal decisão.
fonte
A avaliação parcial é uma estrutura conceitual relevante para relacionar intérpretes e compiladores.
Linguagens de programação são especificações (escritas em alguns relatórios, como R5RS ou n1570 ). Eles não são software, portanto nem faz sentido falar em desempenho . Mas alguma linguagem de programação pode ter várias implementações, incluindo intérpretes e compiladores .
Mesmo em linguagens tradicionalmente compiladas (ou seja, linguagens cujas implementações geralmente são compiladoras) como C, algumas partes são frequentemente interpretadas. Por exemplo, a cadeia de controlo de formato de printf (definido no padrão C) é muitas vezes "interpretado" (pela biblioteca padrão C , o qual tem uma
printf
função utilizando técnicas argumentos variáveis) mas alguns compiladores (incluindo GCC ) são capazes -in limitada específica casos - 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 (para gerar código de máquina em tempo de execução ). Um bom exemplo é o luajit . Outras implementações (por exemplo, Python, Ocaml, Java, Parrot, Lua) estão traduzindo o código-fonte em um bytecode que é então interpretado.
SBCL é um "compilador" Common Lisp que converte dinamicamente toda interação REPL (e chama para
eval
etc ...) em código de máquina. Então você sente que é um intérprete. A maioria das implementações de JavaScript em navegadores (por exemplo, v8 ) usa técnicas de compilação JIT.Em outras palavras, a diferença entre intérpretes e compiladores é muito imprecisa (na verdade, existe um continuum entre ambos) e, na prática, a maioria das implementações de linguagem de programação geralmente tem uma faceta tanto de intérprete quanto de compilador (pelo menos para código de bytes).
Uma implementação pode ser rápida ou lenta, independentemente do uso da 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 com eficiência por meio da análise de todo o programa ).
Para alguns tipos de problemas, vale a pena projetar o software com algumas abordagens de metaprogramação e fornecer acelerações importantes. Você pode imaginar que, com alguma entrada específica, seu programa gera dinamicamente código especializado para processá-lo. Isso é possível com C ou C ++ (usando alguma biblioteca JIT ou gerando algum código C, compilando-o como um plug-in que é carregado dinamicamente).
Veja também esta pergunta relacionada sobre Python, e que
fonte
Para códigos como
A = A + B
, que podem compilar até uma ou duas instruções da máquina, cada uma levando um certo número de ciclos. Nenhum intérprete pode fazer a mesma coisa nesse número de ciclos por um motivo simples.O intérprete também executa um conjunto de instruções próprio (chame-os de códigos de bytes, códigos-p, idioma intermediário, o que for). Cada vez que vê um código de byte como ADD, ele precisa procurar de alguma forma e ramificar para o código que faz a adição.
Na próxima vez que o vir, ele precisará repetir essa pesquisa, a menos que tenha uma maneira de lembrar a pesquisa anterior. Se ele tem uma maneira de lembrar a pesquisa anterior, não é mais o que chamamos de "intérprete", mas sim um compilador just-in-time, ou JITter.
Por outro lado...
Para códigos como
callSomeFunction( ... some args ...)
, quantos ciclos são gastos entre inserir esse código e deixá-lo? Tudo depende do que acontece lá dentrocallSomeFunction
. Pode ser alguns e trilhões, mesmo quecallSomeFunction
ele próprio seja 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 as línguas interpretadas têm um valor próprio, como, não há necessidade de compilá-las. (A "compilação" da sintaxe da superfície para códigos de bytes leva um tempo trivial. Veja R ou MATLAB, por exemplo.)
Além disso, é necessária flexibilidade para níveis inteligentes de programação. Na Sociedade da mente de Minsky , capítulo 6.4 B- Brains, existem programas A que lidam com o mundo, e existem programas B que lidam com programas A, e pode haver outros níveis. Programas que escrevem e gerenciam outros programas podem ser realizados com mais facilidade em sistemas interpretativos.
No Lisp, você pode escrever
(+ A B)
para adicionar A e B, mas uma vez escrito, você só pode executá-lo ou não. Você também pode escrever o(eval (list '+ 'A 'B))
que constrói o programa e depois o executa. Poderia construir algo diferente.O assunto do programa é outro programa . É mais fácil escrever em uma linguagem interpretada (embora, como Jörg ressalte, as versões mais recentes do Lisp, enquanto elas
eval
compilam em tempo real, não têm a penalidade de velocidade de interpretação).fonte
eval
eapply
funções, que são intérpretes.eval
não é interpretado. E nem éapply
. Certamente existem implementações que contêm intérpretes, mas a SBCL não.eval
não é interpretar ed . É uma interpretar er .Depende, mais ou menos, mas como regra geral o ambiente compilado - seja por meio do JIT ou estaticamente compilado - será mais rápido para muitas tarefas intensivas em computação - assumindo por simplicidade o mesmo idioma.
Parte do motivo é que as linguagens interpretadas precisam ter um loop de loop de interpretador que lê uma instrução, seleciona a ação apropriada a ser executada e executada. Na melhor das hipóteses, como a interpretação de bytecode em Python ou Java (como a antiga JVM fazia), ele tem uma sobrecarga de poucas instruções e causou estragos com o preditor de ramificação - sem a última, você pode esperar grandes penalidades devido a erros de previsão. Mesmo um JIT muito burro 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 alterações, você pode obter o código em execução na GPU (exoneração de responsabilidade: trabalho para a nVidia - qualquer opinião aqui expressa é minha e não representa a visão do meu empregador). Dessa forma, você pode escrever códigos curtos e poderosos de nível superior sem se preocupar com detalhes - alguém se preocupou com isso e investiu tempo e recursos na otimização em linguagem de baixo nível. Não há nada herdado e isso não impede, por exemplo, que o Matlab faça o JIT do código, mas muitas vezes não há razão para a sobrecarga de chamar a rotina de alto nível ser mínima em comparação com o tempo gasto nas de baixo nível.
TL; DR - os programas compilados têm enormes benefícios de desempenho em relação aos interpretados (para comparação de maçãs com maçãs, 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 for gasto principalmente nas bibliotecas). Também a implementação é importante.
fonte
Sua suposição é bem fundamentada, embora seja uma suposição.
Não vou abordar as razões pelas quais o código compilado deve ser mais rápido que o código interpretado: se você souber como os computadores funcionam, isso será óbvio. A diferença pode ser de magnitude para certos tipos de problemas. Se o revisor contestar seriamente esse caso geral, ele não saberá do que está falando.
O ponto em que eles podem ter razão é se a diferença é significativa no tipo de aplicativo que você está desenvolvendo. Se é principalmente E / S ou chama principalmente bibliotecas compiladas e não possui muita computação, a sobrecarga do processo de interpretação pode ser realmente insignificante.
Mas o ponto do meu post é o seguinte: como especialista em TI, você será chamado frequentemente para tomar decisões rápidas com base em um conhecimento geral de como as coisas devem funcionar. Fazer um teste específico pode fornecer uma resposta mais precisa, mas custará muito mais e não chegará lá primeiro.
Mas de tempos em tempos você é pego de surpresa. Já aconteceu comigo. Você faz uma boa suposição e depois descobre que não levou em consideração a estupidez do mundo.
Mas não posso explicar tão bem quanto meu desenho animado 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 por precaução.
fonte
A menos que você use algo exótico, seu problema não será o desempenho de uma linguagem interpretada A e da linguagem compilada B.
Como se você / sua equipe conhece A e não B e, portanto, escreve um código muito melhor em A que B, pode ter um desempenho muito melhor em A que B. Se você tem pessoas com experiência em um idioma e o idioma / bibliotecas consegue, trabalho que você precisa, cumpri-lo.
Aqui está um link sobre regex em vários idiomas; você verá que o regex é implementado melhor em algum idioma, mesmo se compilado ou não: http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna
fonte
Acho que não é uma boa ideia falar sobre o desempenho de duas tecnologias apenas com base no fato de uma ser compilada e a outra ser interpretada. Conforme indicado em outras respostas, pode depender da área de aplicação (alguns idiomas podem ser otimizados para executar algumas operações muito rapidamente e fazer outras coisas mais lentamente), bem como da experiência de pessoas que estão prestes a usar essa tecnologia.
Não acho razoável esperar que você obtenha um aumento de desempenho se pegar alguns excelentes codificadores de linguagem interpretada e fornecer a eles alguma tecnologia com a qual eles não estão familiarizados - talvez, em teoria, o último PODE resultar em melhor desempenho, mas, na realidade, sem as habilidades e a experiência necessárias, você não utilizará 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 a alguns desenvolvedores qualificados para manter um código complicado, mas altamente otimizado, do que apenas compre mais equipamento para lidar com a implementação menos eficiente, de modo que também deve ser considerado ao escolher a tecnologia.
fonte
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 encontrei alguns testes comparativos e os citei. Existem muitos deles, de pessoas como a Microsoft ou universidades de renome. 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.
Segundo, você pode executar uma referência própria, talvez usando um pedaço representativo do código em questão ou algo semelhante que você já tenha. Execute-o 1000 vezes durante a noite para que realmente haja uma diferença mensurável.
Nesse 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 com clareza, com diagramas, se possível, declarando todas as suposições e definindo todos os dados utilizados.
fonte
Eu argumentaria que qualquer linguagem dinâmica tem uma vantagem sobre as compiladas estaticamente: "Otimizações de tempo de execução"
Essa é uma das razões pelas quais o Java pode ser mais rápido que o C ++
Sim, carregar um idioma digitado dinamicamente sempre terá o custo da tradução e estará em desvantagem. Porém, uma vez executado, o intérprete pode criar um perfil e aprimorar caminhos de código frequentes com informações de tempo de execução que idiomas estáticos 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
fonte
Esta seria a minha abordagem:
Em geral, os intérpretes são compilados; portanto, toda tecnologia interpretada nada mais é do que uma tecnologia compilada, se analisada em um nível baixo. Portanto, as tecnologias compiladas são apenas mais e com mais possibilidades, você nunca pode piorar se for inteligente (o que geralmente é). Depende da quantidade de informações disponíveis no momento da compilação e da quantidade de informações disponíveis apenas no tempo de execução e da qualidade dos compiladores e intérpretes, mas teoricamente sempre será possível pelo menos igualar o desempenho de qualquer intérprete a um compilador adequado, apenas porque os intérpretes são fabricados por compiladores. Isso é possível, não significa que é o caso dos seus técnicos A e B.
Na prática, basta informar o revisor sobre todos os benchmarks disponíveis onde os sistemas compilados e interpretados são comparados. Em seguida, peça a ele para sugerir um intérprete que supere seu algoritmo específico codificado em Assembly otimizado.
Talvez se deva acrescentar que qualquer afirmação geral desse tipo não ajuda em nada quando se compara dois técnicos específicos A e B. A escolha de A e B importa muito, muito mais, do que se eles forem interpretados ou compilados.
fonte