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.
programming-languages
compilers
Rodrigo Valente
fonte
fonte
Respostas:
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.
fonte
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.
fonte
Existem diferentes fatores para escolher X em vez de Y, como
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á.
fonte
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.
fonte
*p++=*q++;
em muitas máquinas teria sido mais rápido do quearray1[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".-O0
isso, 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.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:
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:não há como o mecanismo JavaScript saber o que
g()
pode fazer comi
[ou comg
ele próprio nesse sentido. Comog
oui
pode legitimamente se transformari
em 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 parai
oug
. 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 identificari
e funcionarg
uma vez, em vez de precisar procurá-los em todas as passagens do loop - uma grande economia de tempo.fonte
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.
fonte
É 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?
fonte
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
Python
e 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 C
compilador versusIntel C
compilador. (Pesquise o benchmark do compilador)fonte