Por que o Go é tão lento (em comparação com o Java)?

109

Como pudemos ver no The Computer Language Benchmarks Game em 2010:

  • Go é em média 10x mais lento que C
  • Go é 3x mais lento que Java !?

Como pode ser, tendo em mente que o compilador Go produz código nativo para execução?
Compiladores imaturos para Go? Ou há algum problema intrínseco com a linguagem Go?

EDIT:
A maioria das respostas nega lentidão intrínseca do Go languge, alegando que o problema reside em compiladores imaturos.
Portanto, fiz alguns testes próprios para calcular os números de Fibonacci : O algoritmo iterativo é executado em Go (freebsd, 6g) com a samevelocidade de C (com opção O3). O recursivo maçante roda em Go 2 timesmais lento do que em C (com a opção -O3; com -O0 - o mesmo). Mas eu não vi uma queda de 10x como no jogo de benchmarks.

Oleg Razgulyaev
fonte
36
Para ser justo, C é ASM disfarçado, e Java tem algumas otimizações sérias nos bastidores atualmente.
Matthew Scharley
16
Talvez o benchmark também não reflita os pontos fortes do Go. Pode ser que outros benchmarks sejam realmente mais rápidos do que isso. Além disso, geralmente não é o desempenho, mas a legibilidade do código que conta mais.
extraneon
7
@extraneon: Eu concordo. Lembre-se, Go foi projetado para o Google e o Google executa rotineiramente código em 2 milhões de núcleos. O jogo Benchmarks usa apenas 4 núcleos, eu acredito.
Jörg W Mittag
4
@extraneon: Concordo em geral, mas Go foi projetado especificamente com a velocidade em mente, como em "os programas resultantes são executados quase tão rapidamente quanto o código C ou C ++ comparável".
shosti
4
Sua pergunta pressupõe muito: "A maioria das respostas nega a lentidão intrínseca do idioma Go" é uma frase incorreta para uso em uma pergunta. Você tem uma pergunta a fazer ou uma declaração a fazer? Consulte c2.com/cgi/wiki?HostileStudent para entender seu erro.
Chris

Respostas:

102

Os compiladores 6g e 8g não são particularmente otimizadores, então o código que eles produzem não é particularmente rápido.

Eles são projetados para serem executados com rapidez e produzirem código OK (há um pouco de otimização). gccgousa os passes de otimização existentes do GCC e pode fornecer uma comparação mais precisa com C, mas o gccgo ainda não está completo com os recursos.

Os valores de referência referem-se quase inteiramente à qualidade da implementação. Eles não têm muito a ver com a linguagem como tal, exceto na medida em que a implementação gasta o tempo de execução dando suporte a recursos de linguagem que o benchmark realmente não precisa. Na maioria das linguagens compiladas, um compilador suficientemente inteligente poderia, em teoria, retirar o que não é necessário, mas chega um ponto em que você está manipulando a demo, já que poucos usuários reais da linguagem escreveriam programas que não usassem esse recurso . Tirar as coisas do caminho sem removê-las totalmente (por exemplo, prever destinos de chamadas virtuais em Java compilado por JIT) começa a ficar complicado.

FWIW, meu próprio teste muito trivial com Go quando eu estava dando uma olhada nele (um loop de adição de inteiro, basicamente), o gccgo produziu código próximo ao fim rápido do intervalo entre gcc -O0e gcc -O2para o equivalente C. Go não é inerentemente lento, mas os compiladores ainda não fazem tudo. Não é surpreendente para um idioma com 10 minutos.

Steve Jessop
fonte
7
Além disso, pode ser que os programas Go em The Computer Language Benchmarks Game não sejam tão otimizados quanto os programas C e Java.
el.pescado
E entre gcc -O0 e gcc -O3? Existe alguma intenção de que os compiladores "façam tudo"?
igouy
@igouy: bem, tenho quase certeza de que há uma intenção do gccgo fazer a coleta de lixo, o que atualmente não acontece. Existem ainda alguns recursos para ir para os compiladores g, por exemplo, eles não usam threads de host particularmente bem (especificamente, o agendador goroutine não é preventivo). Além disso, não sei os planos do Google, se os compiladores g serão otimizados intensamente ou se apenas o gccgo o fará.
Steve Jessop
1
@xitrium: Acho que a intenção do Go é que as implementações não precisem ser programadas de forma cooperativa, eles podem se antecipar se quiserem. Veja, por exemplo , code.google.com/p/go/issues/detail?id=543 , que não foi encerrado como "sem sentido, corrigir este bug chamado contradiria a definição da linguagem Go", o que deveria ser se Implementações de Go são proibidas de se antecipar :-) O problema era agravado pelo fato de que, por padrão, Go usava apenas uma única thread de host, não importando quantas goroutines pudessem ser executadas.
Steve Jessop
6
A resposta pode estar um pouco desatualizada agora. Recentemente, o primeiro beta do Go 1.1 foi lançado , eles afirmam que o desempenho dos programas compilados aumenta em cerca de 30% a 40%. Alguém, por favor, faça esses testes novamente.
fuz
51

Na próxima versão do Go FAQ , algo semelhante ao seguinte deve aparecer.

atuação

Por que o Go tem um desempenho ruim no benchmark X?

Um dos objetivos de design do Go é abordar o desempenho de C para programas comparáveis, mas em alguns benchmarks ele se sai muito mal, incluindo vários em teste / bancada. Os mais lentos dependem de bibliotecas para as quais versões de desempenho comparável não estão disponíveis no Go. Por exemplo, pidigits depende de um pacote matemático de multiprecisão, e as versões C, ao contrário de Go, usam GMP (que é escrito em assembler otimizado). Benchmarks que dependem de expressões regulares (regex-dna, por exemplo) são essencialmente comparando o pacote de expressão regular do Go com bibliotecas de expressão regular altamente otimizadas, como PCRE.

Os jogos de benchmark são vencidos por meio de ajustes extensos e as versões Go da maioria dos benchmarks precisam de atenção. Se você medir programas C e Go comparáveis ​​(complemento reverso é um exemplo), você verá que as duas linguagens estão muito mais próximas em desempenho bruto do que este conjunto indicaria.

Ainda assim, há espaço para melhorias. Os compiladores são bons, mas poderiam ser melhores, muitas bibliotecas precisam de um grande trabalho de desempenho e o coletor de lixo ainda não é rápido o suficiente (mesmo se fosse, tomar cuidado para não gerar lixo desnecessário pode ter um efeito enorme).

E aqui estão mais alguns detalhes sobre The Computer Benchmarks Game de um tópico recente da lista de discussão.

Coleta de lixo e desempenho no gccgo (1)

Coleta de lixo e desempenho no gccgo (2)

É importante notar que o jogo de benchmarks de computador é apenas um jogo. Pessoas com experiência em medição de desempenho e planejamento de capacidade combinam cuidadosamente cargas de trabalho semelhantes entre realistas e reais; eles não jogam.

PeterSO
fonte
1
E aqui estão alguns detalhes desse mesmo tópico que você excluiu - groups.google.com/group/golang-nuts/msg/2e568d2888970308
igouy
3
É importante notar que "benchmarks são um crock" - não apenas os benchmarks publicados como o jogo de benchmarks - shootout.alioth.debian.org/flawed-benchmarks.php
igouy
18
(e todos ...) Claro que é um "jogo" , mas quando vejo que Go é apenas duas vezes mais lento que o mais rápido nesses benchmarks, minha primeira impressão é "uau, Go parece rápido" , porque eu sei que esses benchmarks são defeituoso. Pelo contrário, quando vejo Ruby sendo 65 vezes mais lento que o mais rápido, penso comigo mesmo "não vou usar Ruby para meu próximo esforço concorrente numericamente intensivo" . Portanto, pode ser um "jogo", mas há alguma verdade nisso se você o considerar com cautela.
SyntaxT3rr0r
O planejamento de capacidade tem um aspecto muito importante: custo. Se você vai precisar de caixas X ou 2 * X, faz uma grande diferença no final. E como ninguém pode estimar exatamente o que será executado no futuro com eles, a melhor aposta é dar uma olhada nas diferentes cargas de trabalho. Eu verifiquei algumas implementações desses e achei que eles eram geralmente OK. Acho que os resultados podem ser usados ​​como base para estimativas.
Agoston Horvath
Geralmente, os sistemas do mundo real são limitados por E / S, não pela CPU. Portanto, se Go é 2x ou 5x mais lento, dificilmente faz tanta diferença para o planejamento de capacidade quanto failover, balanceamento de carga, cache, topologia de banco de dados e outros. É por isso que aplicativos na escala do YouTube podem executar muitos de seus sistemas em Python.
Sujoy Gupta
34

Minha resposta não é tão técnica quanto a de todo mundo, mas acho que ainda é relevante. Eu vi os mesmos benchmarks no jogo Computer Benchmarks quando decidi começar a aprender Go. Mas, honestamente, acho que todos esses benchmarks sintéticos são inúteis em termos de decidir se Go é rápido o suficiente para você.

Eu escrevi um servidor de mensagens em Python usando Tornado + TornadIO + ZMQ recentemente e, para meu primeiro projeto Go, decidi reescrever o servidor em Go. Até agora, tendo colocado o servidor com a mesma funcionalidade da versão Python, meus testes estão me mostrando um aumento de 4,7x na velocidade do programa Go. Veja bem, eu só estou programando em Go por talvez uma semana e tenho programado em Python por mais de 5 anos.

Go só vai ficar mais rápido à medida que eles continuam a trabalhar nele, e eu acho que realmente se trata de como funciona em um aplicativo do mundo real e não minúsculos benchmarks computacionais. Para mim, Go aparentemente resultou em um programa mais eficiente do que o que eu poderia produzir em Python. Essa é minha opinião sobre a resposta a esta pergunta.

jdi
fonte
3
Você acha que escreverá código Go muito mais devagar do que em Python?
Erik Engheim
7
@AdamSmith - Eu diria que escreveria código Go mais lentamente do que Python apenas porque tenho codificado Python por mais de 7 anos e apenas um pouco Go. Mas em termos de Go versus outras linguagens compiladas estaticamente tipadas, aposto que escreveria Go mais rápido do que outras. Pessoalmente, acho que é a coisa mais próxima da simplicidade do Python com velocidade entre C e C ++
jdi
5
Eu tenho uma história semelhante. Acabei de começar a aprender Go e, de acordo com o Benchmarks Game, Go é MAIS LENTO que o JavaScript V8. Acontece que meu programa, com operações binárias intensas, é executado 10 vezes mais rápido com código Go não otimizado do que em VM V8 altamente otimizado. Go pode ser mais lento que C em muitas operações, no entanto, ninguém está escrevendo sites em C. Go já é uma opção perfeitamente viável e só deve ficar melhor à medida que novas bibliotecas, frameworks e ferramentas surgem.
se __name__ for Nenhum
1
@ user962247, esta é uma afirmação maluca e falsa. Tenho escrito Go há anos e é muito rápido. Ninguém afirma que ele vencerá C / C ++ / Java em todos os benchmarks sintéticos possíveis. Mas vence em alguns (veja o site do jogo de referência). Acredite em alguém que já está escrevendo código Go de produção há anos. É rápido e produtivo.
jdi
6

As coisas mudaram.

Acho que a resposta correta para sua pergunta é contestar a noção de que ir é lento. No momento de sua investigação, seu julgamento foi justificado, mas, desde então, go ganhou muito terreno em termos de desempenho. Agora, ainda não é tão rápido quanto C, mas não está nem perto de ser 10x mais lento, em um sentido geral.

Jogo de benchmarks de linguagem de computador

No momento da redação deste artigo:

source  secs    KB      gz      cpu     cpu load

reverse-complement
1.167x
Go      0.49    88,320  1278    0.84    30% 28% 98% 34%
C gcc   0.42    145,900 812     0.57    0% 26% 20% 100%

pidigits
1.21x
Go      2.10    8,084   603 2.10    0% 100% 1% 1%
C gcc   1.73    1,992   448 1.73    1% 100% 1% 0%

fasta
1.45x
Go      1.97    3,456   1344    5.76    76% 71% 74% 73%
C gcc   1.36    2,800   1993    5.26    96% 97% 100% 97%

regex-dna
1.64x
Go      3.89    369,380 1229    8.29    43% 53% 61% 82%
C gcc   2.43    339,000 2579    5.68    46% 70% 51% 72%

fannkuch-redux
1.72x
Go      15.59   952 900 62.08   100% 100% 100% 100%
C gcc   9.07    1,576   910 35.43   100% 99% 98% 94%

spectral-norm
2x
Go      3.96    2,412   548 15.73   99% 99% 100% 99%
C gcc   1.98    1,776   1139    7.87    99% 99% 100% 99%

n-body
2.27x
Go      21.73   952 1310    21.73   0% 100% 1% 2%
C gcc   9.56    1,000   1490    9.56    1% 100% 1% 1%

k-nucleotide
2.40x
Go      15.48   149,276 1582    54.68   88% 97% 90% 79%
C gcc   6.46    130,076 1500    17.06   51% 37% 89% 88%

mandelbrot
3.19x
Go      5.68    30,756  894 22.56   100% 100% 99% 99%
C gcc   1.78    29,792  911 7.03    100% 99% 99% 98%

Porém, ele sofre brutalmente no benchmark da árvore binária:

binary-trees
12.16x
Go      39.88   361,208 688 152.12  96% 95% 96% 96%
C gcc   3.28    156,780 906 10.12   91% 77% 59% 83%
Tiffon
fonte
Agora está no mesmo nível do Java, mas o Go não foi criado explicitamente para ser mais rápido do que o Java, embora seja usado para as mesmas coisas (aplicativos de rede do lado do servidor)?
MaxB
1
@MaxB não, não foi criado com o objetivo de ser mais rápido que o Java. Ele foi criado com o objetivo de ter bom desempenho, compilação mais rápida do que C ++ e concorrência mais fácil e nativa para permitir que os desenvolvedores sejam mais produtivos. Superar a velocidade de execução de outras línguas não foi um fator determinante.
jdi
5

Apesar da eficiência não tão boa de Go sobre o uso de ciclos de CPU, o modelo de simultaneidade Go é muito mais rápido do que o modelo de thread em Java, por exemplo, e pode ser comparável ao modelo de thread C ++.

Observe que no benchmark thread-ring , Go foi 16x mais rápido que Java. No mesmo cenário, o Go CSP era quase comparável ao C ++, mas usando 4x menos memória.

O grande poder da linguagem Go é seu modelo de simultaneidade, Communicating Sequential Processes, CSP, especificado por Tony Hoare na década de 70, sendo simples de implementar e adequado para necessidades altamente concorrentes.

DLopes
fonte
2

Existem dois motivos básicos pelos quais o Java é mais rápido do que Go e C ++, e pode ser mais rápido do que C em muitos casos:

1) O compilador JIT. Ele pode incorporar chamadas de funções virtuais por meio de vários níveis, mesmo com classes OO, com base no perfil de tempo de execução. Isso não é possível em uma linguagem compilada estaticamente (embora a recompilação mais recente com base no perfil gravado possa ajudar). Isso é muito importante para a maioria dos benchmarks que envolvem algoritmos repetitivos.

2) O GC. A alocação de memória baseada em GC é quase gratuita, em comparação com o malloc. E a penalidade 'gratuita' pode ser amortizada durante todo o tempo de execução - frequentemente ignorada porque o programa termina antes que todo o lixo precise ser coletado.

Existem centenas (milhares?) De desenvolvedores extremamente talentosos tornando o GC / JVM eficiente. Pensar que você pode "codificar melhor do que todos eles" é uma loucura. É um problema de ego humano em seu cerne - os humanos têm dificuldade em aceitar que, com o treinamento adequado por humanos talentosos, o computador terá um desempenho melhor do que os humanos que o programaram.

Aliás, C ++ pode ser tão rápido quanto C se você não usar e dos recursos OO, mas então você está muito perto de apenas programar em C para começar.

Mais importante ainda, as "diferenças de velocidade" nesses testes geralmente não fazem sentido. Os custos de IO são ordens de magnitude mais do que as diferenças de desempenho e, portanto, projetos adequados que minimizam os custos de IO sempre vencem - mesmo em uma linguagem interpretada. Muito poucos sistemas são limitados pela CPU.

Como nota final, as pessoas se referem ao "jogo de benchmarks de linguagem de computador" como uma "medida científica". Os testes são completamente falhos, por exemplo, se você visualizar os testes Java para ninguém. Quando executo os testes no mesmo sistema operacional / hardware, obtenho cerca de 7,6 segundos para Java e 4,7 segundos para C - o que é razoável - não a lentidão 4x dos relatórios de teste. É uma isca de cliques, uma notícia falsa, projetada para gerar tráfego no site.

Como nota final, final ... Eu executei os testes usando Go e demorou 7,9 segundos. O fato de que quando você clica em Go, ele o compara a Java, e quando você clica em Java ele o compara a C, deve ser uma bandeira vermelha para qualquer engenheiro sério.

Para uma comparação do mundo real de Java, Go e C ++, consulte https://www.biorxiv.org/content/10.1101/558056v1 alerta de spoiler, Java sai por cima em desempenho bruto, com Go saindo por cima com uso de memória combinado e tempo de parede.

robert engels
fonte
errado. C ++ É tão rápido quanto C, especialmente quando você usa OOP, essa é a pílula de sua certidão de nascimento. mais abstração (como nas classes) SEM QUALQUER DEGRADAÇÃO DE DESEMPENHO EM TEMPO DE EXECUÇÃO, COM MEMÓRIA DE ZERO BYTES EXTRA. se você não sabe disso, continue brincando com java, c #, go, python etc.
// Aliás, C ++ pode ser tão rápido quanto C se você não usar e dos recursos OO //, mas, para começar, você está muito perto de apenas programar em C //. se você disser isso, terá muito pouca ideia sobre c ++, para seu próprio bem, não o use. c e c ++ odeiam mentes medievais e mágicas, supersticiosas por natureza, tipo, ah, ouvi isso, li na internet, deve ser verdade ... fique longe de c e c ++, eles vão te devolver meu amigo (conselho honesto)
c é o ancestral de c ++. muitas pessoas ainda usam ... c ++ é um c melhor, onde você pode fazer mais sem pagar o preço. os autores java, c # and go não entenderam, bem, claro que sim, mas o que eles podem fazer?!? o mesmo sobre ser compatível com o código (c) existente. oceanos de código c da vida real! python é um brinquedo legal, divirta-se, gostaria que eles acertassem, mas nah, zen do python deveria ter começado com "o compilador é seu amigo" ...
>> mostra a utilização da CPU em 30% para o programa Java << Não —— "1% 0% 0% 100%".
igouy
1
@igouy Admito que esse é um erro que provavelmente cometi - quando vi o carregamento, estava interpretando em termos de 'carregamento do sistema' e assumindo usuário / sistema / io / ocioso - meu erro, e foi um erro substancial.
robert engels
1

Acho que um fato frequentemente esquecido é que a compilação JIT pode ser> compilação estática, especialmente para funções ou métodos de ligação tardia (tempo de execução). O hotspot JIT decide em RUNTIME quais métodos inline, ele pode até mesmo ajustar o layout dos dados para o tamanho / arquitetura do cache da CPU em que está rodando. C / C ++ em geral pode compensar (e no geral ainda terá um desempenho melhor) por ter acesso direto ao hardware. As coisas do For Go podem parecer diferentes por serem de alto nível em comparação com C, mas atualmente não possui um compilador / sistema de otimização de tempo de execução. Meu instinto me diz, Go poderia ser mais rápido que Java, pois Go não impõe tanto a perseguição de ponteiro e incentiva uma melhor estrutura de dados localidade + requer menos alocação.

R.Moeller
fonte
1

Na verdade, Go não é apenas elegante e eficiente em tempo de design, mas também tem excelente desempenho em tempo de execução. A chave é usar o sistema operacional correto, ou seja, LINUX. Os resultados do perfil de desempenho no Windows e Mac OS são, por falta de uma palavra melhor, uma ou duas ordens de magnitude inferior.

Dan Marinescu
fonte
0

no linux, o runtime go é super rápido, perfeitamente comparável com c / c ++. o tempo de execução go sob windows e unix não são da mesma liga

a comparação com java não é tão importante, go é tanto para desenvolvimento de sistema quanto de aplicativo (já que java é mais como colarinho azul para desenvolvimento de aplicativo apenas). não entrará em detalhes, mas quando coisas como kubernetes são escritas em go, você percebe que não é um brinquedo amigável para consultores empresariais

Não me lembro do google ter mencionado nenhuma vez sobre o compromisso a que se refere. go tem um bom design, simples, elegante e eficiente para projetar programas de nível de sistema e de aplicativo, tem ponteiros, alocação e desalocação de memória eficiente, evita complicações decorrentes de herança de implementação tão fácil de usar incorretamente, dando a você co-rotinas e outras formas modernas maneiras de escrever aplicativos de alto desempenho dentro do prazo e do orçamento. de novo, go é super rápido no Linux, que é exatamente para o que foi projetado (muito feliz por isso)

Dan Marinescu
fonte
-4

Java e C são mais explícitos com suas definições de dados e métodos (funções). C é tipificado estaticamente e Java nem tanto com seu modelo de herança. Isso significa que a maneira como os dados serão tratados é praticamente definida durante a compilação.

Go é mais implícito com seus dados e definições de funções. As funções integradas são de natureza mais geral, e a falta de uma hierarquia de tipo (como Java ou C ++) dá ao Go uma desvantagem de velocidade.

Lembre-se de que o objetivo do Google para a linguagem Go é ter um meio-termo aceitável entre a velocidade de execução e a velocidade de codificação. Eu acho que eles estão atingindo um bom ponto ideal em suas primeiras tentativas, e as coisas só vão melhorar à medida que mais trabalho é feito.

Se você comparar o Go com linguagens de tipagem mais dinâmica, cuja principal vantagem é a velocidade de codificação, verá a vantagem de velocidade de execução do Go. Go é 8 vezes mais rápido que perl e 6 vezes mais rápido que Ruby 1.9 e Python 3 nos benchmarks que você usou.

De qualquer forma, a melhor pergunta a fazer é Go um bom compromisso em facilidade de programação versus velocidade de execução? Minha resposta é sim e deve melhorar.

Bill C
fonte
20
"a falta de uma hierarquia de tipos (como Java ou C ++) dá a Go uma desvantagem de velocidade" - wut?
Erik Kaplun de
6
"Go é mais implícito com seus dados e definições de função." Incorreta. Você quer dizer como os tipos podem implementar métodos sem serem explícitos sobre isso? O compilador detecta a associação da interface de tipo. Isso é rápido. "As funções integradas são de natureza mais geral" não, as funções integradas são, como tudo o mais, compiladas. A mesma coisa acontece com os modelos C ++. "a falta de uma hierarquia de tipo (como Java ou C ++) dá ao Go uma desvantagem de velocidade" - incorreto, uma hierarquia de tipo não tem nada a ver com a execução em tempo de execução.
Malcolm