Ao ouvir o podcast StackOverflow, o jab continua aparecendo que "programadores reais" escrevem em C, e que C é muito mais rápido porque está "próximo à máquina". Deixando a afirmação anterior para outro post, o que há de especial no C que permite que ele seja mais rápido que em outros idiomas? Ou, de outra forma: o que impede outras linguagens de serem compiladas em binário que roda tão rápido quanto C?
c
performance
Mike C.
fonte
fonte
Respostas:
Não há muita coisa especial sobre C. Essa é uma das razões pelas quais é rápido.
Idiomas mais novos que oferecem suporte à coleta de lixo , digitação dinâmica e outras facilidades que facilitam a criação de programas pelo programador.
O problema é que há uma sobrecarga de processamento adicional que prejudicará o desempenho do aplicativo. C não possui nada disso, o que significa que não há sobrecarga, mas significa que o programador precisa ser capaz de alocar memória e liberá-las para evitar vazamentos de memória e deve lidar com a digitação estática de variáveis.
Dito isto, muitas linguagens e plataformas, como Java (com sua Java Virtual Machine ) e .NET (com seu Common Language Runtime) melhoraram o desempenho ao longo dos anos com avanços como a compilação just-in-time que produz código de máquina nativo a partir de bytecode para obter maior desempenho.
fonte
Há uma troca que os designers de C fizeram. Ou seja, eles tomaram a decisão de colocar a velocidade acima da segurança. C não
Quando você indexa em uma matriz, em Java, são necessárias algumas chamadas de métodos na máquina virtual, verificação vinculada e outras verificações de integridade. Isso é válido e absolutamente correto , porque agrega segurança onde é devido. Mas em C, mesmo coisas bastante triviais não são colocadas em segurança. Por exemplo, C não exige que o memcpy verifique se as regiões a serem copiadas se sobrepõem. É não projetado como uma linguagem para programar uma aplicação de negócio grande.
Mas essas decisões de design são não erros na linguagem C . Eles são projetados, pois permitem que os compiladores e criadores de bibliotecas obtenham todo o desempenho do computador. Aqui está o espírito de C, como o documento C Rationale explica:
fonte
Se você gasta um mês para criar algo em C que é executado em 0,05 segundos, e eu passo um dia escrevendo a mesma coisa em Java e em 0,10 segundos, C é realmente mais rápido?
Mas, para responder à sua pergunta, o código C bem escrito geralmente será executado mais rapidamente do que o código bem escrito em outros idiomas, porque parte da escrita "bom" do código C inclui otimizações manuais no nível da máquina.
Embora os compiladores sejam realmente muito inteligentes, eles ainda não são capazes de criar códigos que competem com algoritmos de massagem manual (supondo que as "mãos" pertençam a um bom programador C).
Editar:
Muitos comentários são do tipo "eu escrevo em C e não penso em otimizações".
Mas, para pegar um exemplo específico deste post :
Em Delphi, eu poderia escrever isso:
e no CI escreva isto:
Mas quantas otimizações existem na versão C? Tomamos muitas decisões sobre implementação que não penso na versão Delphi. Como uma string é implementada? Em Delphi, eu não vejo isso. Em C, decidi que seria um ponteiro para uma matriz de números inteiros ASCII, que chamamos de caracteres. Em C, testamos a existência de um personagem de cada vez. No Delphi, eu uso o Pos.
E este é apenas um pequeno exemplo. Em um programa grande, um programador C precisa tomar esse tipo de decisão de baixo nível com todas as poucas linhas de código. Ele adiciona um executável artesanal, otimizado à mão.
fonte
Eu não vê-lo já, então eu vou dizer: C tende a ser mais rápido porque quase tudo é escrito em C .
Java é construído em C, Python é construído em C (ou Java ou .NET etc.), Perl é etc. O sistema operacional é escrito em C, as máquinas virtuais são escritas em C, os compiladores são escritos em C, os intérpretes são escritos em C. Algumas coisas ainda estão escritas na linguagem Assembly, que tende a ser ainda mais rápida. Mais e mais coisas estão sendo escritas em outra coisa, que é escrita em C.
Cada instrução que você escreve em outros idiomas (não no Assembly) geralmente é implementada como várias instruções em C, que são compiladas no código de máquina nativo. Como esses outros idiomas tendem a existir para obter um nível de abstração mais alto que C, essas instruções extras necessárias em C tendem a se concentrar em adicionar segurança, adicionar complexidade e fornecer tratamento de erros. Geralmente, essas são coisas boas, mas têm um custo e seus nomes são velocidade e tamanho .
Pessoalmente, escrevi literalmente dezenas de idiomas, abrangendo a maior parte do espectro disponível, e pessoalmente busquei a mágica que você sugere:
Após alguns anos de pesquisa, minha resposta é Python (em C). Você pode querer dar uma olhada. A propósito, você também pode ir para o Assembly a partir do Python (com alguma ajuda menor de uma biblioteca especial).
Por outro lado, o código incorreto pode ser escrito em qualquer idioma . Portanto, o código C (ou montagem) não é automaticamente mais rápido. Da mesma forma, alguns truques de otimização podem aproximar partes do código de linguagem de nível mais alto do nível de desempenho do C. bruto.
Aproveitar.
fonte
Existem muitas perguntas - principalmente as que não estou qualificado para responder. Mas para este último:
Em uma palavra, abstração.
C está a apenas um ou dois níveis de abstração da linguagem de máquina. As linguagens Java e .Net estão em um mínimo de 3 níveis de abstração do assembler. Não tenho certeza sobre Python e Ruby.
Normalmente, quanto mais brinquedos programadores (tipos de dados complexos, etc.), mais longe você está da linguagem de máquina e mais tradução precisa ser feita.
Estou aqui e ali, mas essa é a essência básica.
Atualização ------- Existem bons comentários neste post com mais detalhes.
fonte
Não é tão rápido que C seja rápido quanto o modelo de custo de C seja transparente . Se um programa C é lento, é lento de uma maneira óbvia: executando várias instruções. Comparado com o custo das operações em C, operações de alto nível em objetos (especialmente reflexão) ou seqüências de caracteres podem ter custos que não são óbvios.
Duas linguagens que geralmente compilam em binários que são tão rápidos quanto C são o ML padrão (usando o compilador MLton ) e o Objective Caml . Se você verificar o jogo de benchmarks, verá que, para alguns benchmarks, como árvores binárias, a versão do OCaml é mais rápida que C. (não encontrei nenhuma entrada do MLton.) Mas não leve o jogo muito a sério; como diz um jogo, os resultados geralmente refletem quanto esforço as pessoas dedicam ao ajuste do código.
fonte
C nem sempre é mais rápido.
C é mais lento do que, por exemplo, o Modern Fortran.
C é geralmente mais lento que Java para algumas coisas. (Especialmente depois que o compilador JIT analisou seu código)
C permite que o alias do ponteiro aconteça, o que significa que algumas boas otimizações não são possíveis. Especialmente quando você tem várias unidades de execução, isso causa interrupções na busca de dados. Ow.
A suposição de que a aritmética do ponteiro funciona realmente causa um desempenho lento em algumas famílias de CPU (PIC particularmente!).
Basicamente, quando você obtém uma unidade vetorial ou um compilador paralelo, o C fede e o Fortran moderno roda mais rápido.
Os truques do programador C como thunking (modificando o executável em tempo real) causam paradas de pré-busca da CPU.
Você entendeu?
E nosso bom amigo, o x86, executa um conjunto de instruções que hoje em dia tem pouca relação com a arquitetura real da CPU. Registros sombra, otimizadores de armazenamento de carga, tudo na CPU. Então, C está próximo ao metal virtual. O verdadeiro metal, a Intel não deixa você ver. (Historicamente, as CPUs VLIW foram um pouco difíceis, talvez isso não seja tão ruim.)
Se você programar em C em um DSP de alto desempenho (talvez um DSP da TI?), O compilador precisará fazer algumas coisas complicadas para desenrolar o C nas várias unidades de execução paralela. Portanto, nesse caso, C não está perto do metal, mas está perto do compilador, que fará a otimização de todo o programa. Esquisito.
E, finalmente, algumas CPUs (www.ajile.com) executam bytecodes Java em hardware. C usaria uma PITA para usar nessa CPU.
fonte
Nada. Linguagens modernas como Java ou .NET langs são mais orientadas à produtividade do programador do que ao desempenho. O hardware é barato hoje em dia. Além disso, a compilação para representação intermediária oferece muitos bônus, como segurança, portabilidade etc. O .NET CLR pode tirar proveito de diferentes hardwares - por exemplo, você não precisa otimizar / recompilar manualmente o programa para usar o conjunto de instruções SSE.
fonte
Os principais fatores são que é uma linguagem de tipo estatístico e compilada no código de máquina. Além disso, como é um idioma de baixo nível, geralmente não faz nada que você não solicite.
Esses são outros fatores que vêm à mente.
A maioria das linguagens de tipo estático pode ser compilada com a mesma rapidez ou rapidez que C, especialmente se elas podem fazer suposições que C não pode por causa de aliasing de ponteiro, etc.
fonte
Eu acho que você esqueceu que a linguagem Assembly também é uma linguagem :)
Mas, falando sério, os programas em C são mais rápidos apenas quando o programador sabe o que está fazendo. Você pode escrever facilmente um programa em C que seja mais lento que os programas escritos em outros idiomas que executam o mesmo trabalho.
A razão pela qual C é mais rápido é porque ele é projetado dessa maneira. Permite fazer várias coisas de "nível inferior" que ajudam o compilador a otimizar o código. Ou, digamos, você, o programador, é responsável por otimizar o código. Mas muitas vezes é bastante complicado e propenso a erros.
Outros idiomas, como outros já mencionados, concentram-se mais na produtividade do programador. Geralmente, acredita-se que o tempo do programador é muito mais caro que o tempo da máquina (mesmo nos velhos tempos). Portanto, faz muito sentido minimizar o tempo que os programadores gastam na gravação e depuração de programas, em vez do tempo de execução dos programas. Para fazer isso, você sacrificará um pouco o que pode fazer para tornar o programa mais rápido, porque muitas coisas são automatizadas.
fonte
Na maioria das vezes, toda instrução C corresponde a muito poucas instruções do assembler. Você está essencialmente escrevendo código de máquina de nível superior, para ter controle sobre quase tudo o que o processador faz. Muitas outras linguagens compiladas, como C ++, possuem muitas instruções simples que podem se transformar em muito mais código do que você imagina (funções virtuais, construtores de cópias etc.). E linguagens interpretadas como Java ou Ruby têm outra camada de código. instruções que você nunca vê - a Máquina Virtual ou o Intérprete.
fonte
Eu sei que muitas pessoas disseram isso de uma maneira longa, mas:
fonte
C ++ é mais rápido, em média (como era inicialmente, em grande parte um superconjunto de C, embora haja algumas diferenças). No entanto, para benchmarks específicos, geralmente há outro idioma que é mais rápido.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/
fannjuch-redux
foi o mais rápido em Scalan-body
efasta
foram mais rápidos em Ada.spectral-norm
foi o mais rápido em Fortran.reverse-complement
,mandelbrot
Epidigits
foram os mais rápidos no ATS.regex-dna
foi o mais rápido em JavaScript.chameneou-redux
foi mais rápido o Java 7.thread-ring
foi o mais rápido em Haskell.O restante dos benchmarks foi mais rápido em C ou C ++.
fonte
extern "C"
não tem nada a ver com C ++ ser um super conjunto de C.system("bash script.sh");
funciona para qualquer script do bash e, portanto, C é um superconjunto do bash.extern "C"
fornece a ligação C em C ++ devido à confusão de nomes. Enquanto chamar X como um superconjunto de Y significa que qualquer coisa que possa ser feita em Y também pode ser feita em X, o que não é verdade para C ++. Existem algumas construções de linguagem que são válidas em C, mas não em C ++.bash
seja um programa de linha de comando disponível. Se tivesse e incluísse qual versão / especificação do bash precisava ser suportada, consideraria superconjunto.struct foo { int: this; }; typedef float foo;
Muitas dessas respostas fornecem razões válidas para o fato de C ser ou não mais rápido (em geral ou em cenários específicos). É inegável que:
Apesar disso, há algo mais que notei que, penso, afeta o desempenho comparativo de C vs. muitos outros idiomas mais do que qualquer outro fator. A saber:
Outros idiomas geralmente facilitam a gravação de código que é executado mais lentamente. Muitas vezes, é até encorajado pelas filosofias de design da linguagem. Corolário: é mais provável que um programador C escreva código que não executa operações desnecessárias.
Como exemplo, considere um programa simples do Windows no qual uma única janela principal é criada. A versão AC preencheria uma
WNDCLASS[EX]
estrutura que seria passada paraRegisterClass[Ex]
, depois chamariaCreateWindow[Ex]
e inseriria um loop de mensagens. Código altamente simplificado e abreviado a seguir:Um programa equivalente em C # poderia ser apenas uma linha de código:
Essa linha de código fornece toda a funcionalidade que quase 20 linhas de código C fizeram e adiciona algumas coisas que deixamos de fora, como a verificação de erros. A biblioteca mais rica e completa (em comparação com as usadas em um projeto C típico) trabalhou muito para nós, liberando nosso tempo para escrever muitos outros trechos de código que nos parecem curtos, mas envolvem muitos passos nos bastidores.
Mas uma rica biblioteca que permite o inchaço fácil e rápido do código não é realmente o meu ponto. Meu ponto de vista é mais aparente quando você começa a examinar o que realmente acontece quando nossa pequena linha de execução realmente é executada. Para se divertir, habilite o acesso à fonte .NET no Visual Studio 2008 ou superior e entre na linha simples acima. Uma das pequenas jóias divertidas que você encontrará é este comentário no getter para
Control.CreateParams
:Dez vezes . As informações aproximadamente equivalentes à soma do que é armazenado em uma
WNDCLASSEX
estrutura e do que é passadoCreateWindowEx
são recuperadas daControl
classe dez vezes antes de serem armazenadas em umaWNDCLASSEX
estrutura e repassadas paraRegisterClassEx
eCreateWindowEx
.Em suma, o número de instruções executadas para executar esta tarefa muito básica é de 2 a 3 ordens de magnitude a mais em C # do que em C. Parte disso se deve ao uso de uma biblioteca rica em recursos, que é necessariamente generalizada versus nosso código C simples que faz exatamente o que precisamos e nada mais. Mas parte disso se deve ao fato de a natureza modularizada e orientada a objetos da estrutura .NET se prestar a muitas repetições de execução que geralmente são evitadas por uma abordagem processual.
Não estou tentando escolher C # ou o .NET framework. Também não estou dizendo que modularização, generalização, recursos de biblioteca / linguagem, OOP etc. são coisas ruins . Eu costumava fazer a maior parte do meu desenvolvimento em C, posteriormente em C ++ e, mais recentemente, em C #. Da mesma forma, antes de C, eu usava principalmente montagem. E a cada passo "mais alto" meu idioma aumenta, escrevo programas melhores, mais sustentáveis e mais robustos em menos tempo. No entanto, eles tendem a executar um pouco mais devagar.
fonte
Eu não acho que alguém tenha mencionado o fato de que muito mais esforço foi colocado nos compiladores C do que em qualquer outro compilador, com talvez a exceção do Java.
O C é extremamente otimizado por muitos dos motivos já mencionados - mais do que quase qualquer outro idioma. Portanto, se a mesma quantidade de esforço for colocada em outros compiladores de idiomas, C provavelmente continuará no topo.
Acho que há pelo menos uma linguagem candidata que, com esforço, poderia ser otimizada melhor que C e, portanto, poderíamos ver implementações que produzem binários mais rápidos. Estou pensando no digital mars D, porque o criador teve o cuidado de criar uma linguagem que poderia ser melhor otimizada do que C. Pode haver outras linguagens com essa possibilidade. No entanto, não consigo imaginar que qualquer linguagem tenha compiladores mais do que apenas alguns por cento mais rápidos que os melhores compiladores C. Eu adoraria estar errado.
Eu acho que a verdadeira "fruta baixa" estará em idiomas projetados para facilitar a otimização dos seres humanos. Um programador experiente pode tornar qualquer linguagem mais rápida - mas às vezes você precisa fazer coisas ridículas ou usar construções não naturais para fazer isso acontecer. Embora sempre exija esforço, uma boa linguagem deve produzir código relativamente rápido sem ter que ficar obcecado com a maneira exata como o programa foi escrito.
Também é importante (pelo menos para mim) que o código do pior caso tenda a ser rápido. Existem inúmeras "provas" na Web de que o Java é tão rápido ou mais rápido que o C, mas isso se baseia em exemplos de seleção de cereja. Não sou muito fã de C, mas sei que QUALQUER COISA que escrevo em C vai correr bem. Com o Java, "provavelmente" será executado dentro de 15% da velocidade, geralmente dentro de 25%, mas em alguns casos pode ser muito pior. Todos os casos em que é tão rápido ou dentro de alguns por cento geralmente são devidos à maior parte do tempo gasto no código da biblioteca, que é C altamente otimizado de qualquer maneira.
fonte
Na verdade, isso é um pouco de falsidade perpetuada. Embora seja verdade que os programas C são frequentemente mais rápidos, nem sempre é esse o caso, especialmente se o programador C não for muito bom nisso.
Um grande buraco evidente que as pessoas tendem a esquecer é quando o programa precisa bloquear algum tipo de IO, como a entrada do usuário em qualquer programa da GUI. Nesses casos, não importa realmente qual idioma você usa, pois você está limitado pela taxa na qual os dados podem chegar, e não pela rapidez com que é possível processá-los. Nesse caso, não importa muito se você estiver usando C, Java, C # ou mesmo Perl; você simplesmente não pode ir mais rápido do que os dados podem entrar.
A outra coisa importante é que o uso da coleta de lixo e o não uso de ponteiros adequados permitem que a máquina virtual faça várias otimizações não disponíveis em outros idiomas. Por exemplo, a JVM é capaz de mover objetos na pilha para desfragmentá-la. Isso torna as alocações futuras muito mais rápidas, pois o próximo índice pode ser simplesmente usado, em vez de procurá-lo em uma tabela. As JVMs modernas também não precisam desalocar a memória; em vez disso, eles apenas movem os objetos ativos quando o GC e a memória gasta dos objetos mortos são recuperados essencialmente de graça.
Isso também traz um ponto interessante sobre C e mais ainda em C ++. Existe uma filosofia de design como "Se você não precisa, não paga". O problema é que, se você quiser, acaba pagando pelo nariz. Por exemplo, a implementação da vtable em Java tende a ser muito melhor do que as implementações em C ++, portanto, as chamadas de funções virtuais são muito mais rápidas. Por outro lado, você não tem escolha a não ser usar funções virtuais em Java e elas ainda custam algo, mas em programas que usam muitas funções virtuais, o custo reduzido aumenta.
fonte
Não se trata tanto da linguagem quanto das ferramentas e bibliotecas. As bibliotecas e compiladores disponíveis para C são muito mais antigos do que para idiomas mais novos. Você pode pensar que isso os tornaria mais lentos, mas au contraire.
Essas bibliotecas foram gravadas em um momento em que o poder de processamento e a memória eram muito importantes. Eles precisavam ser escritos com muita eficiência para funcionar. Os desenvolvedores de compiladores C também tiveram muito tempo para trabalhar em todos os tipos de otimizações inteligentes para diferentes processadores. A maturidade e a ampla adoção de C proporcionam uma vantagem significativa em relação a outros idiomas da mesma idade. Ele também oferece a C uma vantagem de velocidade em relação às ferramentas mais recentes que não enfatizam o desempenho bruto tanto quanto o C precisava.
fonte
A falta de abstração é o que torna C mais rápido. Se você escreve uma declaração de saída, sabe exatamente o que está acontecendo. Se você escrever uma instrução de saída em java, ela será compilada em um arquivo de classe que será executado em uma máquina virtual, introduzindo uma camada de abstração. A falta de recursos orientados a objetos como parte da linguagem também aumenta sua velocidade, com menos código sendo gerado. Se você usa C como uma linguagem orientada a objetos, está fazendo toda a codificação para coisas como classes, herança, etc. Isso significa, em vez disso, tornar algo generalizado o suficiente para todos com a quantidade de código e a penalidade de desempenho que exige que você escreva apenas o que você precisa para fazer o trabalho.
fonte
É incrível ver o velho mito "C / C ++ deve ser mais rápido que Java porque Java é interpretado" ainda está vivo e chutando. Há artigos que remontam alguns anos , bem como artigos mais recentes , que explicam com conceitos ou medidas por que isso nem sempre é o caso .
As implementações atuais de máquinas virtuais (e não apenas a JVM, por sinal) podem tirar proveito das informações coletadas durante a execução do programa para ajustar dinamicamente o código enquanto ele é executado, usando uma variedade de técnicas:
e vários outros ajustes com base no conhecimento do que o código está realmente fazendo e nas características reais do ambiente em que está sendo executado.
fonte
O código mais rápido seria o código da máquina cuidadosamente criado à mão. Assembler será quase tão bom. Ambos são de nível muito baixo e é preciso muito código para escrever. C está um pouco acima do assembler. Você ainda tem a capacidade de controlar as coisas em um nível muito baixo na máquina real, mas há abstração suficiente para torná-la mais rápida e fácil do que a montadora. Outros idiomas, como C # e JAVA, são ainda mais abstratos. Enquanto Assembler e código de máquina são chamados de linguagens de baixo nível, C # e JAVA (e muitos outros) são chamados de linguagens de alto nível. C às vezes é chamado de linguagem de nível médio.
fonte
Não tome a palavra de alguém, observe a desmontagem para C e seu idioma de escolha em qualquer parte crítica de desempenho do seu código. Eu acho que você pode simplesmente olhar na janela de desmontagem em tempo de execução no Visual Studio para ver desmontado .Net. Deveria ser possível se complicado para Java usando windbg, embora, se você fizer isso com .Net, muitos dos problemas sejam os mesmos.
Não gosto de escrever em C se não for necessário, mas acho que muitas das afirmações feitas nessas respostas que defendem a velocidade de idiomas diferentes de C podem ser deixadas de lado simplesmente desmontando a mesma rotina em C e no idioma de sua escolha de nível superior, especialmente se houver muitos dados envolvidos, como é comum em aplicativos críticos de desempenho. Fortran pode ser uma exceção em sua área de especialização, não sei. É mais alto que C?
Na primeira vez em que comparei o código JITed com o código nativo, resolvi toda e qualquer dúvida sobre se o código .Net podia ser executado comparativamente ao código C. O nível extra de abstração e todas as verificações de segurança têm um custo significativo. Os mesmos custos provavelmente se aplicariam ao Java, mas não aceite minha palavra, tente algo em que o desempenho seja crítico. (Alguém sabe o suficiente sobre o JITed Java para localizar um procedimento compilado na memória? Certamente deve ser possível)
fonte
1) Como outros já disseram, C faz menos por você. Sem variáveis de inicialização, sem verificação de limites de matriz, sem gerenciamento de memória, etc. Esses recursos em outros idiomas custam ciclos de memória e CPU que C não gasta.
2) Respostas dizendo que C é menos abstrato e, portanto, mais rápido, são apenas metade corretas, eu acho. Tecnicamente falando, se você tivesse um "compilador suficientemente avançado" para o idioma X, o idioma X poderia se aproximar ou igual à velocidade de C. A diferença com C é que, uma vez que ele mapeia tão obviamente (se você fez um curso de arquitetura) e diretamente à linguagem assembly que mesmo um compilador ingênuo pode fazer um trabalho decente. Para algo como Python, você precisa de um compilador muito avançado para prever os tipos prováveis de objetos e gerar código de máquina rapidamente - a semântica de C é simples o suficiente para que um compilador simples possa se sair bem.
fonte
Nos velhos tempos, havia apenas dois tipos de idiomas: compilados e interpretados.
As linguagens compiladas utilizaram um "compilador" para ler a sintaxe da linguagem e convertê-la em código de linguagem de montagem idêntico, o que poderia ser apenas diretamente na CPU. As linguagens interpretadas usavam alguns esquemas diferentes, mas essencialmente a sintaxe da linguagem foi convertida em uma forma intermediária e, em seguida, executada em um "intérprete", um ambiente para a execução do código.
Assim, de certa forma, havia outra "camada" - o intérprete - entre o código e a máquina. E, como sempre acontece em um computador, mais significa que mais recursos são usados. Os intérpretes eram mais lentos, porque precisavam realizar mais operações.
Mais recentemente, vimos mais linguagens híbridas como Java, que empregam um compilador e um intérprete para fazê-las funcionar. É complicado, mas uma JVM é mais rápida, mais sofisticada e muito mais otimizada do que os antigos intérpretes; portanto, há uma mudança muito melhor de desempenho (ao longo do tempo) mais próximo do código compilado direto. Obviamente, os compiladores mais recentes também têm truques de otimização mais sofisticados, de modo que tendem a gerar código muito melhor do que costumavam. Mas a maioria das otimizações, na maioria das vezes (embora nem sempre), faz algum tipo de troca, de modo que elas nem sempre são mais rápidas em todas as circunstâncias. Como todo o resto, nada é de graça, então os otimizadores devem se gabar de algum lugar (embora muitas vezes o usem em tempo de compilação para economizar tempo de execução da CPU).
Voltando ao C, é uma linguagem simples, que pode ser compilada em um conjunto bastante otimizado e executada diretamente na máquina de destino. Em C, se você incrementa um número inteiro, é mais do que provável que seja apenas uma etapa do assembler na CPU; em Java, no entanto, pode acabar sendo muito mais do que isso (e também pode incluir um pouco de coleta de lixo: -) C oferece uma abstração muito mais próxima da máquina (o montador é o mais próximo), mas você acaba tendo que fazer muito mais trabalho para fazê-lo funcionar e não é tão protegido, fácil de usar ou amigável. A maioria dos outros idiomas oferece uma abstração mais alta e cuida de mais detalhes subjacentes, mas em troca de sua funcionalidade avançada, eles exigem mais recursos para serem executados. Ao generalizar algumas soluções, você precisa lidar com uma ampla variedade de computadores,
Paulo.
fonte
++i
pode ser compilado para "adicionar [ebp - 8], 1". Para não dizer que busca, incremento, armazenamento ainda não está acontecendo, mas isso é resolvido pela CPU e é apenas uma instrução, como Paul disse.Deixando de lado técnicas avançadas de otimização, como otimização de hot spot , meta-algoritmos pré-compilados e várias formas de paralelismo , a velocidade fundamental de uma linguagem se correlaciona fortemente com a complexidade implícita dos bastidores necessária para dar suporte às operações que normalmente ser especificado dentro de loops internos .
Talvez o mais óbvio seja a verificação de validade em referências indiretas à memória - como a verificação de indicadores
null
e a verificação de índices em relação aos limites da matriz. A maioria dos idiomas de alto nível executa essas verificações implicitamente, mas C não. No entanto, isso não é necessariamente uma limitação fundamental dessas outras linguagens - um compilador suficientemente inteligente pode ser capaz de remover essas verificações dos circuitos internos de um algoritmo através de alguma forma de movimento de código invariante em loop .A vantagem mais fundamental do C (e, de maneira semelhante, o C ++ estreitamente relacionado) é uma forte dependência da alocação de memória baseada em pilha , que é inerentemente rápida para alocação, desalocação e acesso. Em C (e C ++), a pilha de chamadas primária pode ser usada para alocação de primitivos, matrizes e agregados (
struct
/class
).Enquanto C oferece a capacidade de alocar dinamicamente memória de tamanho e vida útil arbitrários (usando o chamado 'heap'), isso é evitado por padrão (a pilha é usada).
Tentadoramente, às vezes é possível replicar a estratégia de alocação de memória C nos ambientes de tempo de execução de outras linguagens de programação. Isso foi demonstrado pelo asm.js , que permite que o código escrito em C ou C ++ seja traduzido em um subconjunto de JavaScript e executado com segurança em um ambiente de navegador da Web - com velocidade quase nativa.
De certa forma, outra área em que C e C ++ ofuscam a maioria das outras linguagens em termos de velocidade é a capacidade de integrar-se perfeitamente aos conjuntos de instruções da máquina nativa. Um exemplo notável disso é a disponibilidade (dependente do compilador e da plataforma) das intrínsecas do SIMD que suportam a construção de algoritmos personalizados que tiram vantagem do hardware de processamento paralelo agora quase onipresente - enquanto ainda utilizam as abstrações de alocação de dados fornecidas pelo idioma (menor alocação de registro de nível de nível é gerenciada pelo compilador).
fonte
Eu encontrei uma resposta no link sobre por que algumas linguagens são mais rápidas e outras mais lentas, espero que isso esclareça mais sobre por que C ou C ++ é mais rápido que outros. Existem outras linguagens também que são mais rápidas que C, mas não podemos use todos eles. Alguma explicação -
Uma das grandes razões pelas quais o Fortran permanece importante é porque é rápido: as rotinas de processamento de números escritas no Fortran tendem a ser mais rápidas que as rotinas equivalentes, escritas na maioria dos outros idiomas. As linguagens que estão competindo com o Fortran neste espaço - C e C ++ - são usadas porque são competitivas com esse desempenho.
Isso levanta a questão: por que? O que há no C ++ e no Fortran que os tornam mais rápidos e por que eles superam outras linguagens populares, como Java ou Python?
Interpretação versus compilação Há muitas maneiras de categorizar e definir linguagens de programação, de acordo com o estilo de programação que eles incentivam e os recursos que oferecem. Ao analisar o desempenho, a maior distinção é entre linguagens interpretadas e compiladas.
A divisão não é difícil; pelo contrário, há um espectro. Em uma extremidade, temos as linguagens compiladas tradicionais, um grupo que inclui Fortran, C e C ++. Nesses idiomas, há um estágio de compilação discreto que converte o código fonte de um programa em um formato executável que o processador pode usar.
Esse processo de compilação possui várias etapas. O código fonte é analisado e analisado. Erros básicos de codificação, como erros de digitação e ortografia, podem ser detectados neste momento. O código analisado é usado para gerar uma representação na memória, que também pode ser usada para detectar erros - desta vez, erros semânticos, como chamar funções que não existem ou tentar executar operações aritméticas em sequências de texto.
Essa representação na memória é então usada para acionar um gerador de código, a parte que produz código executável. A otimização do código, para melhorar o desempenho do código gerado, é executada em vários momentos nesse processo: otimizações de alto nível podem ser executadas na representação do código e otimizações de nível inferior são usadas na saída do gerador de código.
A execução do código acontece mais tarde. Todo o processo de compilação é simplesmente usado para criar algo que pode ser executado.
No extremo oposto, temos intérpretes. Os intérpretes incluirão um estágio de análise semelhante ao do compilador, mas isso será usado para direcionar a execução direta, com o programa sendo executado imediatamente.
O intérprete mais simples possui um código executável correspondente aos vários recursos suportados pelo idioma - portanto, ele terá funções para adicionar números, unir strings, qualquer que seja o idioma de um determinado idioma. À medida que analisa o código, ele pesquisa a função correspondente e a executa. As variáveis criadas no programa serão mantidas em algum tipo de tabela de pesquisa que mapeia seus nomes para seus dados.
O exemplo mais extremo do estilo do intérprete é algo como um arquivo em lotes ou um script de shell. Nessas linguagens, o código executável nem sempre é embutido no próprio intérprete, mas em programas independentes separados.
Então, por que isso faz diferença no desempenho? Em geral, cada camada de indireção reduz o desempenho. Por exemplo, a maneira mais rápida de adicionar dois números é ter esses dois números nos registradores no processador e usar as instruções de adição do processador. É o que os programas compilados podem fazer; eles podem colocar variáveis em registradores e tirar proveito das instruções do processador. Mas, em programas interpretados, essa mesma adição pode exigir duas pesquisas em uma tabela de variáveis para buscar os valores a serem adicionados e, em seguida, chamar uma função para executar a adição. Essa função pode muito bem usar a mesma instrução de processador usada pelo programa compilado para executar a adição real, mas todo o trabalho extra antes que a instrução possa realmente ser usada torna as coisas mais lentas.
Se você quiser saber mais, consulte a Fonte
fonte
Alguns algoritmos C ++ são mais rápidos que C e algumas implementações de algoritmos ou padrões de design em outras linguagens podem ser mais rápidas que C.
Quando as pessoas dizem que C é rápido e depois passam a falar sobre outro idioma, geralmente usam o desempenho de C como referência.
fonte
Com os compiladores de otimização modernos, é altamente improvável que um programa C puro seja muito mais rápido do que o código .net compilado, se houver. Com o aumento da produtividade que frameworks como .net fornecer o desenvolvedor, você pode fazer coisas em um dia que costumava levar semanas ou meses de C. regulares Juntamente com o custo mais barato de hardware em comparação com o salário de um desenvolvedor, é apenas WAY mais barato para gravação o material em um idioma de alto nível e atire o hardware a qualquer lentidão.
A razão pela qual Jeff e Joel falam sobre C ser a linguagem "real programador" é porque não há manipulação manual em C. Você deve alocar sua própria memória, desalocar essa memória, fazer sua própria verificação de limites etc. Não existe tal coisa como novo objeto (); Não há coleta de lixo, classes, OOP, estruturas de entidade, LINQ, propriedades, atributos, campos ou qualquer coisa assim. Você precisa saber coisas como aritmética do ponteiro e como desreferenciar um ponteiro. E, nesse caso, saiba e entenda o que é um ponteiro. Você precisa saber o que é um quadro de pilha e qual é o ponteiro de instrução. Você precisa conhecer o modelo de memória da arquitetura da CPU em que está trabalhando. Há muita compreensão implícita da arquitetura de um microcomputador (geralmente omicrocomputador em que você está trabalhando) ao programar em C que simplesmente não está presente nem necessário ao programar em algo como C # ou Java. Todas essas informações foram descarregadas para o programador do compilador (ou VM).
fonte
É a diferença entre automático e manual, linguagens de nível superior são abstrações automatizadas. C / C ++ são controlados e manipulados manualmente, mesmo o código de verificação de erros às vezes é um trabalho manual.
C e C ++ também são linguagens compiladas, o que significa que nada disso funciona em todos os lugares, essas linguagens precisam ser ajustadas para o hardware com o qual você trabalha, adicionando uma camada extra de pegadinha. Embora isso esteja um pouco perturbador agora, os compiladores C / C ++ estão se tornando mais comuns em todas as plataformas. Você pode fazer compilações cruzadas entre plataformas. Ainda não é uma situação de execução em todos os lugares, você basicamente instrui o compilador A a compilar no mesmo código a arquitetura diferente do compilador B.
Os idiomas C da linha inferior não devem ser fáceis de entender ou raciocinar; também é por isso que eles são chamados de idiomas de sistemas. Eles surgiram antes de toda essa bobagem de abstração de alto nível. É também por isso que eles não são usados para programação na web de front-end. Eles simplesmente não são adequados para a tarefa, têm o objetivo de resolver problemas complexos que não podem ser resolvidos com ferramentas de linguagem convencionais.
É por isso que você tem coisas malucas como (micro-arquiteturas, drivers, física quântica, jogos AAA, sistemas operacionais), para as quais C e C ++ são adequados. A velocidade e a trituração de números são as principais áreas.
fonte
C é rápido porque é uma linguagem de baixo nível compilada nativamente. Mas C não é o mais rápido. O índice de referência recursivo de Fibonacci mostra que Rust, Crystal e Nim podem ser mais rápidos.
fonte
Existem várias razões, incluindo:
fonte