timeit & Microbenchmarks
Microbenchmarks medem pequenos trechos de código com precisão. O módulo timeit elimina armadilhas comuns de medição de tempo (coleta de lixo, sobrecarga de configuração) para comparações justas.
Receita
import timeit
time_a = timeit.timeit("[x*x for x in range(1000)]", number=10000)
time_b = timeit.timeit("list(map(lambda x: x*x, range(1000)))", number=10000)
print(f"compreensão: {time_a:.4f}s, map: {time_b:.4f}s")Quando usar isso:
- Comparando duas implementações da mesma lógica
- Validando se uma otimização realmente ajuda
- Benchmarking de alternativas da biblioteca padrão vs. de terceiros
Exemplo de Trabalho
import timeit
setup = """
from pathlib import Path
data = list(range(10000))
"""
stmt_list = "[x * 2 for x in data]"
stmt_gen = "list(x * 2 for x in data)"
t_list = timeit.timeit(stmt_list, setup=setup, number=1000)
t_gen = timeit.timeit(stmt_gen, setup=setup, number=1000)
print(f"list comp: {t_list:.4f}s, gen: {t_gen:.4f}s, ratio: {t_gen/t_list:.2f}x")# Linha de comando
# python -m timeit "[x*x for x in range(1000)]"
# python -m timeit -s "import math" "math.sqrt(2)"O que isso demonstra:
setupé executado uma vez;stmté executadonumbervezes- Comparação justa com configuração idêntica
- CLI
python -m timeitpara comandos rápidos de uma linha - Relatar a razão, não apenas os tempos absolutos
Mergulho Profundo
Regras de Benchmark
- Execute em uma máquina ociosa (feche outros aplicativos)
- Aumente
numberaté que o tempo total seja > 0.2s - Execute várias rodadas; relate a mediana, não o melhor
- Nunca faça benchmark de I/O ou rede no timeit
Armadilhas Comuns
| Armadilha | Correção |
|---|---|
| GC durante a medição | timeit desabilita o GC por padrão |
| Cache frio | Aqueça antes de medir |
| Modo de depuração | Faça benchmark sem -O a menos que esteja medindo a produção |
number minúsculo | Aumente até que a resolução do temporizador seja insignificante |
Gotchas
- Benchmarking de compilações de depuração -
-Oou a configuração de produção são diferentes. Correção: faça benchmark da configuração de implantação. - Conclusões de execução única - o ruído domina. Correção: várias execuções, relate a mediana e o desvio padrão.
- Comparando tamanhos de entrada diferentes - cruzamento O(n) vs O(n^2). Correção: faça benchmark em tamanhos de entrada realistas.
- Otimizando o caminho não principal - o microbenchmark vence, mas sem impacto real. Correção: primeiro, analise o aplicativo completo.
- Eliminação de código morto - o compilador remove resultados não utilizados. Correção: armazene ou use o resultado no loop de benchmark.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| pytest-benchmark | Rastreamento de regressão em CI | Comparação rápida única |
| cProfile | Encontrando o que fazer benchmark | Comparando duas implementações |
| pyperf | Benchmarks estatísticos rigorosos | Verificações rápidas |
FAQs
timeit vs time.perf_counter?
timeit para trechos isolados. perf_counter para medição de tempo de função completa.
Que número devo usar?
Aumente até que o tempo total decorrido seja de 0.2 a 2 segundos. timeit auto-calibra com autorange.
Posso fazer benchmark de código async?
Use asyncio.run() em setup/stmt ou ferramentas de benchmark async dedicadas.
Como faço benchmark com argumentos?
Use setup para definir dados; referencie-os na string stmt.
timeit é thread-safe?
Cada chamada é independente. Para código com threads, faça benchmark do cenário concorrente completo separadamente.
Exemplos de python -m timeit?
python -m timeit "sum(range(1000))" executa com repetições auto-calibradas.
Como evito interferência do GC?
timeit desabilita o GC durante a medição por padrão.
Devo usar %timeit no Jupyter?
Conveniente para exploração. Use o módulo timeit para scripts reproduzíveis.
Como compartilho resultados de benchmark?
Confirme um script de benchmark com number fixo e documente hardware/SO.
Quando o microbenchmark é enganoso?
Quando o trecho não é o ponto crítico da aplicação. Analise primeiro.
Relacionado
- Noções Básicas de Desempenho - mentalidade de medição
- cProfile & Profilers - encontrando pontos críticos
- Melhores Práticas de Desempenho - quando otimizar
- Vetorização com NumPy - benchmarks numéricos
Versões da Stack: Esta página foi escrita para Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ e uv 0.6+.