Profiling de Código Python: Identificando Gargalos
1. Conceito de Profiling
Profiling não altera a lógica do programa, mas coleta informações detalhadas sobre execução:
Tempo gasto por função
Número de chamadas por função
Uso de memória (em alguns casos)
Gargalos em loops ou chamadas recursivas
Objetivo: otimizar apenas onde realmente há impacto, evitando micro-otimizações desnecessárias.
2. Ferramentas Nativas
2.1 time e timeit
Para medições rápidas de blocos de código:
import time
inicio = time.time()
total = sum(range(1000000))
fim = time.time()
print(f"Tempo de execução: {fim - inicio:.4f} segundos")
Para medições mais precisas e repetidas, use timeit:
import timeit
tempo = timeit.timeit("sum(range(1000))", number=1000)
print(f"Tempo médio: {tempo:.6f} segundos")
timeitevita interferência de variáveis globais e outras execuções paralelas.
2.2 cProfile
Profiling completo e detalhado de funções e chamadas internas.
import cProfile
def funcao_lenta():
total = 0
for i in range(100000):
total += i**2
return total
cProfile.run("funcao_lenta()")
Saída típica:
5 function calls in 0.020 seconds
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.019 0.019 0.019 0.019 <stdin>:1(funcao_lenta)
tottime: tempo gasto dentro da função, sem subfunçõescumtime: tempo total acumulado, incluindo subfunções
2.3 pstats
import cProfile, pstats
prof = cProfile.Profile()
prof.enable()
funcao_lenta()
prof.disable()
stats = pstats.Stats(prof)
stats.sort_stats("cumulative").print_stats(10)
sort_stats("cumulative")ordena pelas funções que mais impactam o tempo total.Útil para identificar rapidamente os gargalos principais.
3. Profiling Avançado
3.1 line_profiler
Permite medir o tempo linha a linha, excelente para funções complexas.
Instalação:
pip install line_profiler
Uso:
from line_profiler import LineProfiler
def funcao_complexa():
total = 0
for i in range(1000):
total += i**2
return total
prof = LineProfiler()
prof.add_function(funcao_complexa)
prof.enable_by_count()
funcao_complexa()
prof.print_stats()
Identifica exatamente quais linhas consomem mais tempo dentro de uma função.
3.2 memory_profiler
Foca em uso de memória linha a linha.
Instalando:
pip install memory-profiler
Exemplo:
from memory_profiler import profile
@profile
def funcao_memoria():
a = [i**2 for i in range(100000)]
return sum(a)
funcao_memoria()
Mostra crescimento de memória e possíveis leaks.
4. Técnicas de Profiling Profissional
Perfis iniciais globais com
cProfilepara identificar funções críticas.Perfis linha a linha com
line_profilerpara otimizar loops ou cálculos intensivos.Monitoramento de memória com
memory_profilerem aplicações que lidam com grandes datasets.Perfis de chamadas assíncronas usando módulos como
yappioupy-spy.Visualização de resultados com ferramentas como SnakeViz ou Py-Spy para análise gráfica.
Exemplo com SnakeViz:
pip install snakeviz
python -m cProfile -o resultado.prof meu_script.py
snakeviz resultado.prof
Abre um dashboard interativo com gráficos de chamadas e tempo.
5. Boas Práticas de Profiling
Nunca otimize sem medir: priorize gargalos reais.
Use ferramentas nativas para profiling rápido, externas para análises detalhadas.
Combine profiling de tempo e memória em aplicações críticas.
Evite medir dentro de loops repetitivos desnecessariamente, pode distorcer resultados.
Documente e versiona análises de performance, permitindo comparações ao longo do desenvolvimento.
6. Exemplos de Otimização Baseada em Profiling
Loop lento: substituir
for i in range(len(lista))por enumerate ou compreensões.Funções repetitivas: usar memoization (
functools.lru_cache).Operações pesadas em listas: substituir listas por generators para economizar memória.
Cálculos intensivos: considerar Numba ou Cython para compilação JIT.
7. Conclusão
Profiling é essencial para entender onde o código realmente gasta tempo e memória.
Ferramentas como
cProfile,line_profilerememory_profilerpermitem análise detalhada.Aplicações avançadas incluem dashboards gráficos, perfis de chamadas assíncronas e otimizações inteligentes.
Combinando profiling com boas práticas de design e POO avançada, você consegue código Python eficiente, escalável e confiável.

Comentários
Postar um comentário