O que determina a "velocidade" de uma linguagem de programação?


38

Suponha que um programa tenha sido escrito em duas línguas distintas, sejam elas a linguagem X e a linguagem Y, se seus compiladores gerarem o mesmo código de bytes, por que eu deveria usar a linguagem X em vez da linguagem Y? O que define que um idioma é mais rápido que outro?

Eu pergunto isso porque muitas vezes você vê pessoas dizendo coisas como: "C é a linguagem mais rápida, ATS é uma linguagem rápida como C". Eu estava procurando entender a definição de "rápido" para linguagens de programação.


21
Se um programa é mais rápido que outro, significa que eles não podem ter o mesmo código de bytes.
svick

5
Idiomas são apenas uma noção que se usa para escrever programas, então você não pode realmente falar sobre a velocidade de um idioma.
Juho 14/03

1
@ Rafael Eu acho que é fora de tópico, pouco claro e muito amplo. Embora o tópico seja mais adequado à engenharia de software , suspeito que seria fechado por ser "muito amplo" lá.
David Richerby

2
Implementação à parte, "speed" é ambígua, existem velocidades diferentes para implementar, compilar, executar e depurar, e geralmente você trocará algumas pelas outras (caso contrário, todos nós estaríamos usando a linguagem de programação)
Nick T

Como acima. Os idiomas não geram o mesmo código de bytes. Alguns idiomas são mais fáceis de analisar no código de bytes. Alguns têm um nível mais alto de abstração.
superluminário 16/03

Respostas:


23

Há muitos motivos que podem ser considerados para a escolha de um idioma X em detrimento de um idioma Y. Legibilidade do programa, facilidade de programação, portabilidade para muitas plataformas, existência de bons ambientes de programação podem ser esses motivos. No entanto, considerarei apenas a velocidade de execução, conforme solicitado na pergunta. A questão não parece considerar, por exemplo, a velocidade do desenvolvimento.

Dois idiomas podem ser compilados no mesmo código de bytes, mas isso não significa que o mesmo código será produzido,

Na verdade, bytecode é apenas código para uma máquina virtual específica. Ele possui vantagens de engenharia, mas não apresenta diferenças fundamentais na compilação direta de um harware específico. Portanto, você também pode comparar duas linguagens compiladas para execução direta na mesma máquina.

Dito isto, a questão da velocidade relativa das linguagens é antiga, datando dos primeiros compiladores.

Por muitos anos, naqueles primeiros tempos, o profissional considerou que o código escrito à mão era mais rápido que o código compilado. Em outras palavras, a linguagem de máquina foi considerada mais rápida que as linguagens de alto nível, como Cobol ou Fortran. E era mais rápido e geralmente menor. As linguagens de alto nível ainda se desenvolveram porque eram muito mais fáceis de usar para muitas pessoas que não eram cientistas da computação. O custo do uso de linguagens de alto nível tinha até um nome: a taxa de expansão, que poderia dizer respeito ao tamanho do código gerado (uma questão muito importante naqueles tempos) ou ao número de instruções realmente executadas. O conceito era principalmente experimental, mas a proporção era superior a 1 no início, já que os compiladores fizeram um trabalho bastante simples pelos padrões atuais.

Assim, a linguagem de máquina era mais rápida do que o Fortran.

Obviamente, isso mudou ao longo dos anos, à medida que os compiladores se tornaram mais sofisticados, a ponto de que a programação em linguagem assembly agora é muito rara. Para a maioria dos aplicativos, os programas em linguagem assembly competem mal com o código gerado pela otimização de compiladores.

Isso mostra que uma questão importante é a qualidade dos compiladores disponíveis para o idioma considerado, sua capacidade de analisar o código fonte e otimizá-lo de acordo.

Essa capacidade pode depender, em certa medida, dos recursos da linguagem para enfatizar as propriedades estruturais e matemáticas da fonte, a fim de facilitar o trabalho do compilador. Por exemplo, uma linguagem pode permitir a inclusão de instruções sobre as propriedades algébricas de funções definidas pelo usuário, de modo a permitir que o compilador use essas propriedades para fins de otimização.

O processo de compilação pode ser mais fácil, produzindo um código melhor, quando o paradigma de programação da linguagem estiver mais próximo dos recursos das máquinas que interpretarão o código, seja ela real ou virtual.

Outro ponto é se os paradigmas implementados na linguagem estão fechados para o tipo de problema que está sendo programado. É de se esperar que uma linguagem de programação especializada para paradigmas de programação específicos compile de maneira muito eficiente os recursos relacionados a esse paradigma. Portanto, a escolha de uma linguagem de programação pode depender, para maior clareza e rapidez, da escolha de uma linguagem de programação adaptada ao tipo de problema que está sendo programado.

A popularidade de C para programação de sistemas provavelmente se deve ao fato de que C está próximo da arquitetura da máquina e que a programação do sistema também está diretamente relacionada a essa arquitetura.

Algum outro problema será mais facilmente programado, com execução mais rápida usando programação lógica e linguagens de resolução de restrições .

Sistemas reativos complexos podem ser programados de maneira muito eficiente com linguagens de programação síncrona especializadas, como a Esterel, que incorpora conhecimento muito especializado sobre esses sistemas e gera código muito rápido.

Ou, para dar um exemplo extremo, algumas linguagens são altamente especializadas, como linguagens de descrição de sintaxe usadas para programar analisadores. Um gerador de analisador nada mais é do que um compilador para essas linguagens. Obviamente, o Turing não é completo, mas esses compiladores são extremamente bons para sua especialidade: produzir programas de análise eficientes. Sendo o domínio do conhecimento restrito, as técnicas de otimização podem ser muito especializadas e ajustadas com muito cuidado. Esses geradores de analisador geralmente são muito melhores do que o que poderia ser obtido escrevendo código em outro idioma. Existem muitas linguagens altamente especializadas com compiladores que produzem código excelente e rápido para uma classe restrita de problemas.

Portanto, ao escrever um sistema grande, pode ser aconselhável não confiar em um único idioma, mas escolher o melhor idioma para diferentes componentes do sistema. Isso, é claro, levanta problemas de compatibilidade.

Outro ponto que importa frequentemente é simplesmente a existência de bibliotecas eficientes para os tópicos que estão sendo programados.

Finalmente, a velocidade não é o único critério e pode estar em conflito com outros critérios, como segurança de código (por exemplo, com relação a entradas incorretas ou resiliência a erros do sistema), uso de memória, facilidade de programação (embora a compatibilidade de paradigmas possa realmente ajudar a ), tamanho do código do objeto, manutenção do programa etc.

A velocidade nem sempre é o parâmetro mais importante. Além disso, pode assumir diferentes formas, como complexidade, que pode ser complexidade média ou, no pior caso, complexidade. Além disso, em um sistema grande como em um programa menor, há partes em que a velocidade é crítica e outras em que pouco importa. E nem sempre é fácil determinar isso com antecedência.


Obrigado. É algo assim. Eu estava procurando. Era difícil encontrar material para o assunto. Isso esclareceu o suficiente.
Rodrigo Valente

@ RodrigoAraújoValente Obrigado, você pode querer olhar para esta pergunta . Uma visão extremista é que um compilador para a linguagem L pode apenas agrupar um intérprete para L com o código fonte do programa, sem fazer nada. Então você pode fazer melhor tentando otimizar o cálculo do pacote configurável (avaliação parcial). Quanto mais você otimizar e mais rápido será o seu idioma. A questão é então: o que pode ajudá-lo a otimizar? As respostas podem incluir bom conhecimento da área de assunto especializada, ajuda do programador, análises sofisticadas, etc ...
babou

Por "mesmo bytecode", suponho que você queira dizer "mesmo tipo de representação executável". Obviamente, executáveis ​​idênticos serão executados na mesma velocidade (assumindo o mesmo sistema de execução). (Eu provavelmente teria analisado isso de uma perspectiva da informação / comunicação. Em teoria , um programador pode saber tudo sobre o programa e o hardware, enquanto uma linguagem frequentemente restringe a comunicação (limitando quais tranformações são permitidas ou úteis) e o compilador pode não saber . detalhes microarquiteturais compilação e desenvolvimento compilador são analygous para desenvolvimento e treinamento ....
Paul A. Clayton

Isso então mostra o que os humanos geralmente são bons (por exemplo, reconhecendo padrões gerais) versus o que os computadores geralmente são bons (por exemplo, manutenção de registros e "aritmética"). Além disso, a comunicação de informações em tempo de execução geralmente é mais amigável ao computador (a otimização guiada por perfil pode superar alguma falta de informações comunicadas pela linguagem de programação). Otimização dinâmica seria impraticável com os programadores humanos ...
Paul A. Clayton

(embora o mesmo possa ser dito sobre a gravação de todos os softwares em montagem por programadores qualificados visando hardware específico, quando o software fosse otimizado não apenas o hardware seria alterado, mas o software seria obsoleto).)
Paul A. Clayton

16

Enquanto tudo acaba sendo executado na CPU * , há várias diferenças entre diferentes idiomas. Aqui estão alguns exemplos.

Linguagens interpretadas Algumas linguagens são interpretadas em vez de compiladas , por exemplo, Python, Ruby e Matlab. Isso significa que o código Python e Ruby não compila com o código da máquina, mas é interpretado on-the-fly. É possível compilar Python e Ruby em uma máquina virtual (veja o próximo ponto). Veja também esta pergunta . Interpretado é geralmente mais lento que o código compilado por vários motivos. Não só a própria interpretação pode ser lenta, como também é mais difícil fazer otimizações. No entanto, se o seu código passar a maior parte do tempo em funções de biblioteca (o caso do Matlab), o desempenho não será prejudicado.

Máquina virtual Algumas linguagens são compiladas no bytecode , um "código de máquina" inventado que é então interpretado. Os exemplos por excelência são Java e C #. Embora o bytecode possa ser convertido em código de máquina rapidamente, o código provavelmente continuará mais lento. No caso de Java, uma máquina virtual é usada para portabilidade. No caso do C #, pode haver outras preocupações, como segurança.

Sobrecarga Alguns idiomas trocam eficiência por segurança. Por exemplo, algumas versões do Pascal verificariam se você não acessa uma matriz fora dos limites. O código C # é "gerenciado" e isso tem um custo. Outro exemplo comum é a coleta de lixo, que economiza tempo para o programador, mas não é tão eficiente quanto o gerenciamento prático de memória. Existem outras fontes de sobrecarga, como infraestrutura para tratamento de exceções ou suporte à programação orientada a objetos.

* Na verdade, os sistemas hoje em dia de alta performance também executar código no GPUs e até mesmo em FPGAs.


Então, basicamente, se eu precisar de mais desempenho, devo usar os idiomas compilados? E sobre os paradigmas? Existe uma razão para escolher funcional em vez de oop, ou vice-versa?
Rodrigo Valente

Sua observação sobre a coleta de lixo é um pouco simplista. Nem sempre é possível decidir estaticamente quando a memória alocada não é mais usada. Mesmo quando decidido, pode ser muito difícil determinar sem cometer erros. Portanto, o GC às vezes é necessário e geralmente mais seguro (como verificar os limites da matriz). Além disso, pode ser combinado com liberação explícita.
21715

@ RodrigoAraújoValente Depends. Geralmente, o código de baixa qualidade é compilado para um código de baixa qualidade. Talvez o código que você pode escrever em Python é realmente mais rápido do que o código que você pode escrever em C.
Raphael

nit: como explica a questão é ligada ao, python não é realmente interpretado "on-the-fly" :)
Eevee

Nenhum dos idiomas mencionados na seção interpretada é interpretado em tempo real. Python é compilado no bytecode, Ruby foi compilado no AST, mas acredito que agora está compilado no bytecode. Matlab, acredito que agora seja realmente compilado pelo JIT. Na verdade, eu não conheço nenhuma implementação de linguagem que não seja de nicho que interprete as coisas em tempo real, em vez de pelo menos compilar com algum tipo de representação de máquina virtual.
Winston Ewert 15/03

5

Existem diferentes fatores para escolher X em vez de Y, como

  • Facilidade de aprendizado
  • Facilidade de compreensão
  • Velocidade de desenvolvimento
  • Ajuda na aplicação do código correto
  • Desempenho do código compilado
  • Ambientes de plataforma suportados
  • Portabilidade
  • Adequado para a finalidade

Algumas linguagens são adequadas para o desenvolvimento de projetos de negócios como C # ou Python, mas, por outro lado, algumas são boas para programação de sistemas como C ++.

Você deve determinar em qual plataforma você vai trabalhar e qual aplicativo você criará.


1
Então, como eu determino o desempenho do código compilado? Isso foi basicamente o que me fez fazer essa pergunta.
Rodrigo Valente

6
Essa resposta certamente tem bons conselhos, mas não vejo como ela responde à pergunta, que trata da velocidade como um fator de escolha para um idioma.
babou

@ RodrigoAraújoValente Eles podem até não ser um código compilado (se o seu idioma for interpretado).
Raphael

1
Você pode adicionar "Boas bibliotecas" e "Boas ferramentas".
Raphael

@ RodrigoAraújoValente Você o executa e cria um perfil.
Kyle

2

A linguagem de programação "mais rápida" que você pode obter com qualquer plataforma é a linguagem assembly para o chipset com o qual está lidando. Nesse nível, não há traduções. No entanto, é necessário ter algum conhecimento de como o chipset executa instruções, especialmente aquelas que podem fazer coisas em paralelo.

A conversão de C para montagem é muito "superficial", pois fica próxima de um para um, mas é mais legível. No entanto, possui muitas camadas acima, devido às bibliotecas padrão para melhorar a portabilidade. Não há tantas coisas que o compilador precisaria fazer para obter o código de montagem e as otimizações mais fortes geralmente estão lá para fazer alterações específicas da máquina.

C ++ adiciona uma linguagem mais rica. No entanto, como o idioma adiciona tanta complexidade, fica mais difícil para o compilador criar código ideal para a plataforma.

Então vamos para o outro lado da balança. Idiomas interpretados. Eles tendem a ser os mais lentos porque, além de fazer o trabalho, há algum tempo gasto para analisar o código e convertê-lo em chamadas de máquina.

Então nós temos aqueles no meio. Geralmente eles têm uma camada de máquina virtual otimizada para a plataforma. E o compilador criará código para a máquina virtual executar. Às vezes, isso acontece de uma só vez, como perl, pascal, ruby ​​ou Python. Ou em várias etapas, como java.

Algumas dessas máquinas virtuais adicionam a noção de um compilador JIT que acelera o tempo de execução, criando código de nível de máquina em vez de converter código de byte intermediário.

Algumas máquinas virtuais são de baixo nível, o que permite menos conversão de código de bytes em código de máquina. O que acelera as coisas, mantendo a portabilidade.


Historicamente, o C foi projetado para facilitar a tradução em código de máquina. Cada vez mais, porém, transformar C em código C eficiente exige que um compilador descubra o que um programador estava tentando fazer e depois traduza essa intenção em código de máquina. Por exemplo, historicamente o código de máquina equivalente *p++=*q++;em muitas máquinas teria sido mais rápido do que array1[i]=array2[i];em muitos processadores, mas em muitos processadores o inverso geralmente é verdadeiro e, portanto, os compiladores podem acabar convertendo o estilo antigo de código para o último - dificilmente uma conversão "superficial".
Supercat

Geralmente, se você fizer -O0isso, não fará otimizações. Otimizações são um bônus que você obtém com o compilador, mas o idioma em si pode traduzir quase de um para um para montagem.
Archimedes Trajano

2

Um ponto que ainda não foi mencionado é que, em algumas linguagens, executar o mesmo trecho de código muitas vezes sempre executará a mesma sequência de ações; portanto, o computador precisa determinar apenas uma vez o que a seção do código deve fazer. Um dos principais benefícios do dialeto "use strict" do JavaScript é que, assim que o mecanismo JavaScript descobre o que um pedaço de código faz, ele pode usar essas informações na próxima vez em que for executado; sem "use strict", não pode.

Por exemplo, na ausência de "use strict", um pedaço de código como:

function f() { return x; }

pode retornar uma variável X no contexto de chamada imediata, se houver uma, ou uma variável X de um contexto de chamada externa, ou pode retornar Undefined. Pior, em um loop como:

for (i=0; i<40; i+=1) { g(i); }

não há como o mecanismo JavaScript saber o que g()pode fazer com i[ou com gele próprio nesse sentido. Como gou ipode legitimamente se transformar iem uma sequência, o mecanismo JavaScript não pode simplesmente usar uma adição e comparação numérica no loop, mas deve, em cada passagem pela verificação do loop, verificar se alguma das chamadas de função fez alguma coisa para iou g. Por outro lado, no dialeto "use strict" [um tanto sã], o mecanismo JavaScipt pode examinar o código acima e saber que toda passagem pelo loop usará a mesma variável numérica e chamará a mesma função. Assim, será necessário apenas identificar ie funcionarg uma vez, em vez de precisar procurá-los em todas as passagens do loop - uma grande economia de tempo.


2

Bem, existem algumas respostas bastante profissionais aqui, essa não é próxima delas, mas pode ser intuitiva para você.

Você já deve ter ouvido muitas vezes que, quando precisar executar uma tarefa o mais rápido possível, gostaria de escrever o código que a executa na montagem. Isso ocorre porque você executa apenas os comandos necessários para concluir a tarefa e nada mais. Enquanto em um idioma de alto nível você pode implementar essa tarefa em várias linhas, o compilador ainda precisa convertê-las para o idioma da máquina. Essa tradução nem sempre é minimalista, pois você pode escrevê-la diretamente. Isso significa que a máquina gastará muitos relógios na execução de comandos que você poderia poupar.

Embora os compiladores sejam muito sofisticados hoje em dia, eles ainda não são eficazes como os melhores programadores de montagem.

Continuando nessa direção, esses comandos desnecessários aumentam em quantidade (geralmente) à medida que o idioma é mais nivelado. (isso não é 100% verdadeiro para todos os idiomas de alto nível)

Então, para mim, o idioma X é mais rápido que o idioma Y (em tempo de execução) se, para determinado trecho de código, o código de máquina de X for menor que o de Y.


Montagem totalmente rochas. É preciso um verdadeiro artista para superar os melhores compiladores.
Johan - restabelece Monica

1

É difícil responder a essa pergunta definitivamente porque é muito complexa e multidimensional (é quase como, por exemplo, comparar marcas de carros sobre critérios diversos), mas existem novos estudos científicos, incluindo um excelente repositório de código conhecido como código Rosetta ( visão geral da wikipedia ). Esta pesquisa de Nanz e Furia de 2014 estuda essa questão de maneira definitiva e científica com base nos seguintes critérios típicos e em uma análise quantitativa rara de qualidades tipicamente subjetivas do código. O resumo contém algumas descobertas e generalizações objetivamente fundamentadas. (Esperemos que outros estudos baseados nesses resultados possam ser realizados no futuro.)

  • RQ1. Quais linguagens de programação contribuem para um código mais conciso?

  • RQ2. Quais linguagens de programação são compiladas em executáveis ​​menores?

  • RQ3. Quais linguagens de programação têm melhor desempenho em tempo de execução?

  • RQ4. Quais linguagens de programação usam a memória com mais eficiência?

  • RQ5. Quais linguagens de programação são menos propensas a falhas?

Resumo - Às vezes, os debates sobre linguagens de programação são mais religiosos do que científicos. Perguntas sobre qual idioma é mais sucinto ou eficiente, ou torna os desenvolvedores mais produtivos são discutidas com fervor, e suas respostas são muitas vezes baseadas em histórias e crenças sem fundamento. Neste estudo, usamos o potencial de pesquisa amplamente inexplorado do Rosetta Code, um repositório de códigos de soluções para tarefas comuns de programação em várias linguagens, que oferece um grande conjunto de dados para análise. Nosso estudo é baseado em 7.087 programas de solução correspondentes a 745 tarefas em 8 linguagens amplamente usadas, representando os principais paradigmas de programação (procedural: C e Go; orientado a objetos: C # e Java; funcional: F # e Haskell; scripts: Python e Ruby). Nossa análise estatística revela, principalmente, que: linguagens funcionais e de script são mais concisas do que linguagens processuais e orientadas a objetos; C é difícil de superar quando se trata de velocidade bruta em entradas grandes, mas as diferenças de desempenho em relação às entradas de tamanho moderado são menos pronunciadas e permitem que mesmo idiomas interpretados sejam competitivos; As linguagens compiladas de tipo forte, onde mais defeitos podem ser detectados em tempo de compilação, são menos propensas a falhas de tempo de execução do que as linguagens interpretadas ou de tipo fraco. Discutimos implicações desses resultados para desenvolvedores, designers de linguagem e educadores. onde mais defeitos podem ser detectados em tempo de compilação, são menos propensos a falhas de tempo de execução do que linguagens interpretadas ou de tipo fraco. Discutimos as implicações desses resultados para desenvolvedores, designers de linguagem e educadores. onde mais defeitos podem ser detectados em tempo de compilação, são menos propensos a falhas de tempo de execução do que linguagens interpretadas ou de tipo fraco. Discutimos as implicações desses resultados para desenvolvedores, designers de linguagem e educadores.


0

Linguagens de computador são apenas uma abstração de comandos para explicar ao computador o que fazer.

Você pode até escrever na linguagem do computador Pythone compilá-lo com um compilador C (cython).

Tendo isso em mente, a velocidade das linguagens de computador não pode ser comparada.

Mas você pode comparar compiladores para o mesmo idioma até certo ponto. Por exemplo, GNU Ccompilador versus Intel Ccompilador. (Pesquise o benchmark do compilador)


2
Se você quiser fazer comentários sobre a pergunta, use a caixa de comentários, não sua resposta. Observe que esse é o Computer Science Stack Exchange e a ciência da computação não está programando, assim como a literatura não é um processamento de texto. As questões de programação são ao vivo em Engenharia de Software ou Estouro de Pilha .
David Richerby
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.