O módulo pstats no Python lê, combina, ordena, filtra e apresenta os dados produzidos por cProfile e profile. O profiler coleta eventos de chamadas, retornos e exceções; o pstats transforma esse volume de dados em relatórios que ajudam a localizar funções lentas, chamadas excessivas e algoritmos inadequados.
Profiling não é benchmarking. O profiler adiciona overhead e mede a aplicação inteira sob instrumentação. Use timeit para comparar pequenos trechos em condições controladas e pstats para entender onde uma execução real gastou tempo.
Gere um arquivo de perfil
A linha de comando do cProfile pode gravar os dados em um arquivo binário:
python -m cProfile -o perfil.prof aplicacao.pyQuando o alvo é um módulo:
python -m cProfile -o perfil.prof -m meu_pacote.cliO arquivo não é um formato de intercâmbio estável. Analise-o com a mesma versão, implementação e, idealmente, sistema operacional que o criou.
Abra os dados com Stats
import pstats
estatisticas = pstats.Stats("perfil.prof")
estatisticas.print_stats()O construtor também aceita um objeto cProfile.Profile, vários arquivos ou um stream customizado para a saída.
Entenda as colunas
O relatório padrão apresenta:
ncalls: total de chamadas.tottime: tempo dentro da função, sem subfunções.percall:tottimedividido pelas chamadas.cumtime: tempo na função e em tudo que ela chamou.percallcumulativo: tempo acumulado dividido por chamadas primitivas.
Em funções recursivas, ncalls pode aparecer como total/primitivas.
Ordene por tempo cumulativo
SortKey.CUMULATIVE mostra funções cujas árvores de chamadas consumiram mais tempo.
from pstats import Stats, SortKey
Stats("perfil.prof") \
.sort_stats(SortKey.CUMULATIVE) \
.print_stats(20)Essa é uma boa primeira visão para identificar endpoints, tarefas ou algoritmos de alto nível responsáveis pelo custo.
Ordene por tempo interno
SortKey.TIME destaca funções que gastam tempo no próprio corpo, excluindo subchamadas.
Stats("perfil.prof") \
.sort_stats(SortKey.TIME) \
.print_stats(20)Uma função com cumtime alto e tottime baixo provavelmente delega o custo. Uma função com ambos altos executa trabalho significativo diretamente.
Use SortKey
A enumeração é mais robusta que abreviações em texto. Chaves úteis incluem CALLS, PCALLS, FILENAME, LINE, NAME, NFL, STDNAME, TIME e CUMULATIVE.
stats.sort_stats(
SortKey.NAME,
SortKey.FILENAME,
SortKey.LINE,
)Chaves adicionais servem como critérios de desempate. O comportamento numérico legado deve ser evitado em código novo.
Remova prefixos de caminhos
strip_dirs() deixa o relatório mais curto.
stats.strip_dirs().sort_stats(SortKey.TIME).print_stats()O método modifica o objeto e pode unir entradas que passam a ter mesmo arquivo, linha e nome. Guarde uma versão sem strip quando caminhos completos forem necessários.
Filtre a saída
print_stats() aceita quantidade, fração e expressões regulares.
stats.sort_stats(SortKey.CUMULATIVE)
stats.print_stats(30)
stats.print_stats(0.10)
stats.print_stats("meu_pacote")Restrições são aplicadas na ordem em que aparecem. print_stats(.5, 'servico') primeiro reduz a metade e depois filtra; inverter os argumentos produz outro resultado.
Veja quem chamou uma função
print_callers() responde quais funções chamaram cada entrada selecionada.
stats.sort_stats(SortKey.CUMULATIVE)
stats.print_callers("processar_pedido")Esse relatório ajuda a encontrar um helper barato que ficou caro por ser invocado por muitos caminhos.
Veja o que uma função chamou
print_callees() mostra a direção oposta.
stats.print_callees("processar_pedido")Use callers para entender origem da demanda e callees para decompor o custo interno.
Combine várias execuções
O construtor aceita múltiplos arquivos e agrega funções identificadas pela mesma combinação de arquivo, linha e nome.
stats = pstats.Stats(
"worker-1.prof",
"worker-2.prof",
"worker-3.prof",
)add() incorpora dados posteriores:
stats.add("worker-4.prof")Combine apenas execuções comparáveis. Misturar versões, configurações, volumes ou sistemas diferentes pode produzir conclusões enganosas.
Compare antes e depois
pstats soma arquivos, mas não calcula automaticamente um delta estatístico entre duas versões. Gere relatórios equivalentes, exporte dados estruturados e compare funções relevantes.
Repita várias execuções com a mesma carga, descarte aquecimento quando aplicável e registre commit, versão do Python, máquina e configuração.
Capture a saída em uma string
import io
import pstats
from pstats import SortKey
buffer = io.StringIO()
pstats.Stats("perfil.prof", stream=buffer) \
.sort_stats(SortKey.CUMULATIVE) \
.print_stats(20)
relatorio = buffer.getvalue()Isso permite anexar o relatório a artefatos de CI, dashboards ou tickets. Remova caminhos e dados sensíveis antes de publicar.
Use um Profile em memória
import cProfile
import pstats
profiler = cProfile.Profile()
profiler.enable()
executar_cenario()
profiler.disable()
pstats.Stats(profiler) \
.sort_stats(pstats.SortKey.CUMULATIVE) \
.print_stats(15)Essa abordagem evita arquivo temporário e é útil em testes de desempenho internos. Para processos longos, gravar o dump preserva evidências para análise posterior.
Exporte dados estruturados
get_stats_profile() retorna uma StatsProfile com objetos FunctionProfile.
perfil = stats.get_stats_profile()
for nome, funcao in perfil.func_profiles.items():
print(nome, funcao.cumulative_time)A API facilita JSON, tabelas e alertas, mas nomes de função podem colidir. Preserve arquivo e linha quando construir identificadores.
O navegador interativo
Executado como módulo, pstats abre uma interface de linha de comando:
python -m pstats perfil.profO navegador permite carregar, ordenar, filtrar e mostrar callers ou callees. Ele usa uma interface baseada no módulo cmd no Python.
Tempo cumulativo e algoritmos
Um alto cumtime pode indicar que a função escolheu um algoritmo caro ou chamou repetidamente uma operação externa. Otimizar linhas internas não resolve sempre o problema; reduzir quantidade de trabalho, chamadas e alocações costuma trazer maior impacto.
Quantidade de chamadas
SortKey.CALLS destaca funções invocadas muitas vezes.
stats.sort_stats(SortKey.CALLS).print_stats(20)Um helper minúsculo pode dominar o custo quando aparece milhões de vezes. Também pode revelar loops involuntários e callbacks duplicados.
Profiling e memória
pstats mede chamadas e tempo, não alocações. Para crescimento de memória, compare snapshots com tracemalloc no Python. Use as duas ferramentas separadamente para evitar overhead excessivo e resultados difíceis de interpretar.
Não confunda com bytecode
O relatório é organizado por funções, arquivos e linhas, não por instruções. Para estudar operações compiladas, consulte opcode no Python e dis no Python.
Imports e tempo de inicialização
Quando o perfil mostra custo elevado em imports, modulefinder no Python ajuda a mapear dependências estáticas. Mesmo assim, imports dinâmicos e efeitos de módulos precisam de medição real.
Limitações do profiling determinístico
- O profiler adiciona overhead.
- Funções C podem parecer desproporcionalmente rápidas.
- Operações muito curtas acumulam erro de medição.
- Uma única execução pode não representar a produção.
- I/O externo varia com ambiente.
- Threads e processos exigem coleta planejada.
Use os dados para formular hipóteses e valide alterações com medições repetidas.
Segurança dos arquivos de perfil
Trate dumps como artefatos internos. Eles podem revelar caminhos, nomes de módulos, arquitetura, funções de negócio e padrões de uso. Armazene com controle de acesso e não aceite dumps de origem desconhecida sem isolamento.
O formato não possui garantia de compatibilidade futura e não deve ser usado como API pública.
Boas práticas
- Comece por
CUMULATIVEe depois useTIME. - Filtre para o código da aplicação.
- Inspecione callers e callees.
- Repita cenários representativos.
- Registre ambiente e commit.
- Não trate profiling como benchmark preciso.
- Proteja os dumps.
- Confirme melhorias com nova medição.
Conclusão
O pstats no Python transforma dados brutos de profiling em relatórios acionáveis. Ordenação, filtros, agregação, callers, callees e perfis estruturados ajudam a distinguir funções diretamente lentas de operações caras por delegação ou frequência.
Consulte a documentação oficial do pstats e a documentação do timeit.







