Como medir desempenho em Rust: benchmarking para iniciantes

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que o Rust exige uma abordagem especial para benchmarking?



O Rust é famoso por sua velocidade, mas até a linguagem mais rápida pode ser desacelerada por uma implementação ruim. Você já escreveu um algoritmo em Rust pensando: "Isso vai ser relâmpago!", e depois executou e não entendeu — onde se perderam os microssegundos? Familiar?



Benchmarking em Rust não é apenas iniciar um cronômetro e medir o tempo. É toda uma ciência: é preciso considerar as otimizações do compilador, o cache do processador e até mesmo como o Rust gerencia a memória. Neste artigo, vamos abordar como fazer benchmark de programas em Rust corretamente, para que você obtenha números honestos, e não resultados aleatórios.



Vamos percorrer o caminho desde medições simples com std::time até a ferramenta profissional criterion, usada em projetos reais. Vamos lá!



1. A maneira mais simples: std::time::Instant



Se você precisa "sentir" rapidamente o desempenho de um trecho de código — sem instalar crates, basta inserir a medição diretamente no main. Mas há um problema: o otimizador do Rust pode "descartar" seu código se ele não usar o resultado.



use std::time::Instant;

fn main() { let start = Instant::now();

// Seu código a ser medido let mut sum = 0u64; for i in 0..1_000_000 { sum += i; }

let duration = start.elapsed(); println!("Tempo de execução: {:?}", duration); // Use o resultado obrigatoriamente! println!("Soma: {}", sum);}


Por que não posso simplesmente medir uma única execução?

Uma única execução é uma loteria. O sistema pode estar ocupado, o processador pode estar em throttling, o cache pode estar frio. Um benchmark correto em Rust deve:

  • Aquecer o código (warm-up) — algumas iterações antes da medição
  • Executar o código muitas vezes (milhares de iterações)
  • Calcular a média dos resultados


A implementação manual disso é um caminho para erros. Por isso, a comunidade Rust criou o criterion.



2. Benchmarking profissional: a crate Criterion



Criterion.rs é o padrão de facto para benchmarking em Rust. É usado no próprio compilador rustc e em centenas de crates. Por que ele é tão bom?

  • Aquecimento automático e tratamento estatístico
  • Gráficos e comparação com execuções anteriores
  • Detecção de regressões (se o código ficou mais lento — você saberá)
  • Suporte a benchmarks parametrizados


Instalação e configuração

Adicione ao Cargo.toml:

[dev-dependencies]criterion = { version = "0.5", features = ["html_reports"] }

[[bench]]name = "my_benchmark"harness = false


Crie o arquivo benches/my_benchmark.rs:



use criterion::{black_box, criterion_group, criterion_main, Criterion};

// Função a ser submetida ao benchmarkfn fibonacci(n: u64) -> u64 { match n { 0 => 0, 1 => 1, _ => fibonacci(n - 1) + fibonacci(n - 2), }}

fn bench_fibonacci(c: &mut Criterion) { c.bench_function("fibonacci 20", |b| { // black_box — impede o otimizador de descartar o código b.iter(|| fibonacci(black_box(20))) });}

criterion_group!(benches, bench_fibonacci);criterion_main!(benches);


Execute: cargo bench. Você verá algo como:

fibonacci 20             time:   [24.567 µs 24.789 µs 25.012 µs]


Três números representam o intervalo de confiança (limite inferior, médio e superior). Se o intervalo for estreito — o benchmark é estável.



3. O ingrediente secreto: black_box



Você deve ter notado o black_box no exemplo. Esta é uma função mágica do criterion que impede o LLVM de otimizar os argumentos ou o resultado. Sem ela, seu benchmark pode mostrar 0 ns — porque o compilador simplesmente calculou a constante em tempo de compilação.



Exemplo p

Blogs

Book Recommendations