Skip to content
← Back to projects

Comparativo Performance Linguagens

Comparativo de performance entre 8 linguagens em 11 provas, tudo validado em Docker: Rust, C++, Go, Java, Kotlin, Dart (Flutter), PHP com JIT e Python (CPython/PyPy).

#Comparativo de performance: 8 linguagens, 11 cenários, tudo em Docker

Bateria de benchmarks que compara Rust, C++, Go, Java, Kotlin, Dart (Flutter), PHP com JIT e Python (CPython e PyPy) em onze cargas de trabalho diferentes — do laço numérico puro ao motor de casamento de ordens com latência medida em nanossegundos.

Tudo roda em contêiner, com todas as versões pinadas e todas as imagens no mesmo Debian 13 "trixie" — misturar Alpine (musl) com slim (glibc) troca o alocador no meio da comparação e invalida qualquer conclusão sobre memória.

📄 O relatório completo, com a análise de cada prova, sai em PDF: python3 gerar_pdf_relatorio.py.

#O placar

Colocação Linguagem Soma das posições 1º lugar em Pior posição Memória somada
🥇 Rust 1.98.0 19 8 de 11 753 MB
🥈 C++ (GCC 16.2) 42 2 1 494 MB
🥉 Java 26 43 1 2 373 MB
Go 1.27.1 47 919 MB
Kotlin 2.4.20 52 2 467 MB
Dart 3.13.3 AOT (Flutter) 63 1 388 MB
PHP 8.5.10 (JIT) 64 2 224 MB
Python — PyPy 7.3.23 (JIT) 75 2 392 MB
Python 3.14.7 (CPython) 90 1 896 MB

Medido num Intel i7-10700 (8 núcleos / 16 threads), 31 GB de RAM, Linux 6.x, Docker 29.7. Os seus números vão ser outros — o que deve se repetir são as proporções.

#As onze provas

# Prova O que mede
T01 Mandelbrot Laço numérico puro: ponto flutuante e desvio imprevisível
T02 Crivo de Eratóstenes Inteiros e varredura sequencial de memória
T03 Alocação 5 milhões de objetos curtos: alocador e coletor de lixo
T04 Tabela hash 3 M de inserções + 3 M de buscas com chave textual
T05 Ordenação 10 M de inteiros de 64 bits com a função padrão
T06 JSON (55 MB) Desserializar, agregar e serializar de novo
T07 XML (33 MB) Leitura em fluxo com agregação por atributo
T08 Expressão regular 1 M de linhas de log: casar, extrair e agregar
T09 Paralelismo O mesmo Mandelbrot em 8 núcleos
T10 Motor de casamento 10 M de ordens com latência p50/p99/p99.9 por ordem
T11 Partida a frio Tempo e memória de só o runtime existir

#Como rodar

Requisitos: Docker e Python 3 no host (o resto vive em contêiner).

# 1. baixa as dependências e gera as entradas (~225 MB, semente fixa)
./preparar.sh

# 2. constrói as imagens — versões pinadas
cd docker
for f in rust cpp go jvm dart php pypy cpython cpythonjit; do
  docker build -t "bench-$f:1" -f "Dockerfile.$f" .
done
cd ..

# 3. compila as implementações
docker run --rm -v "$PWD":/bench -w /bench/src/rust bench-rust:1 cargo build --release
docker run --rm -v "$PWD":/bench bench-cpp:1  /bench/compilar_cpp.sh
docker run --rm -v "$PWD":/bench bench-go:1   /bench/compilar_go.sh
docker run --rm -v "$PWD":/bench bench-dart:1 /bench/compilar_dart.sh
docker run --rm -v "$PWD":/bench bench-jvm:1  sh -c 'cd /bench/src/java   && javac -cp "lib/*" -d bin *.java'
docker run --rm -v "$PWD":/bench bench-jvm:1  sh -c 'cd /bench/src/kotlin && kotlinc -cp "../java/lib/jackson-databind.jar:../java/lib/jackson-core.jar:../java/lib/jackson-annotations.jar" -d bin *.kt'

# 4. roda a bateria (uma a duas horas; o CPython puro é o gargalo)
python3 harness.py

# 5. monta as tabelas
python3 montar_tabelas.py

Dá para rodar só uma linguagem ou só uma prova:

python3 harness.py go              # só o Go, nas 11 provas
python3 harness.py go,rust t10_matching   # Go e Rust, só no motor de casamento

#⚠️ Antes de medir qualquer coisa

Confira a carga da máquina: uptime. Acima de 1,5 de média, não meça. Na primeira tentativa desta bateria o PyPy marcou 4,42 s no Mandelbrot com uma compilação rodando ao lado e 1,63 s com a máquina livre — 2,7× de diferença que não tem nada a ver com a linguagem.

#As regras que tornam a comparação honesta

  1. Mesmo algoritmo em todas. Nada de trocar o crivo por uma fatiação esperta em Python ou por SIMD explícito em C++;
  2. Checksum obrigatório. As 9 implementações de cada prova imprimem um checksum, e os checksums batem. Sem isso, o comparativo mediria quem faz menos trabalho;
  3. A biblioteca padrão de cada uma, ou o padrão de fato do ecossistema — é assim que um projeto real nasce;
  4. Sem -march=native e sem afinar o coletor. Nada de GOGC, -Xmx ou troca de alocador: cada runtime roda como sai da caixa;
  5. Todo código dentro de função. O JIT do PHP otimiza corpo de função muito melhor que código no topo do script — eram 3,3× de penalidade num erro da primeira versão;
  6. Empate no tempo desempata pela menor memória. O /usr/bin/time reporta duas casas decimais; duas linguagens que fazem o mesmo trabalho no mesmo tempo não estão empatadas se uma gasta 39 MB e a outra 2 MB;
  7. Mediana de até três execuções, com tempo e pico de RSS medidos pelo /usr/bin/time dentro do contêiner — o custo de subir o contêiner não entra na conta.

#O que este laboratório NÃO mede

  • Rede, disco, banco e concorrência de E/S. Um servidor web real passa a maior parte da vida esperando o banco; nesse regime as diferenças encolhem muito. Isso é especialmente injusto com o Go, cuja maior força — dezenas de milhares de goroutines bloqueadas em E/S — nenhuma prova exercita;
  • Produtividade, tempo de compilação, custo de contratação, maturidade de biblioteca — que decidem projeto mais vezes do que microssegundos.

#Estrutura

.
├── docker/            9 Dockerfiles, um por runtime, com a versão pinada
├── src/               as 9 implementações de cada uma das 11 provas
│   ├── rust/  cpp/  go/  java/  kotlin/  dart/  php/  python/
├── dados/             gerado pelo preparar.sh (não versionado)
├── preparar.sh        baixa dependências e gera as entradas
├── gerar_dados.py     regera as entradas com semente fixa (42)
├── harness.py         executa a bateria e grava resultados/resultados.json
├── montar_tabelas.py  monta as tabelas do relatório
├── montar_anexo.py    monta o anexo com uma linha por (prova × linguagem)
└── resultados/        resultados.json, execucao.log e as tabelas

#Achou um erro?

Ótimo — abra uma issue. Este laboratório já teve três erros corrigidos depois de publicado (máquina carregada, PHP fora de função, desempate sem critério de memória), todos encontrados relendo os próprios números. Benchmark que ninguém contesta é benchmark que ninguém leu.

#👨‍💻 Créditos

Icaro WilliamTio Jobs · Arquiteto de Software 🐙 github.com/icarojobs · 🎓 Jobs Treinamentos

Material de apoio do curso Principal/Senior Rust Engineer.

New version available.