Use essas dicas para analisar seu código e descobrir onde ele é mais ou menos eficiente.

Como "há mais de uma maneira de fazer isso" em Python, pode ser um desafio encontrar a abordagem mais eficiente em termos de memória para algumas tarefas. É aqui que um criador de perfil de memória pode ajudar. Além de rastrear vazamentos, estimar o perfil de memória do seu código ajuda a determinar qual código é eficiente em termos de memória.

Esteja você desenvolvendo um modelo de aprendizado de máquina ou um site com Python, você pode estimar o perfil de memória para scripts, linhas de código individuais ou funções.

Estimar o perfil de memória de toda a sua base de código pode ser impraticável, pois isso pode tornar seu aplicativo significativamente mais lento. Em vez disso, é melhor criar um perfil seletivo de funções ou métodos que você suspeita que possam estar consumindo mais memória. Mas mesmo que você queira fazer isso para todo o seu aplicativo, convém dedicar um módulo isolado para lidar com isso.

Existem muitas bibliotecas de perfis em Python. Alguns dos mais populares são memory_profiler, psutil, Tracemalloc, e Pympler. Este tutorial usa memory_profiler e psutil.

Enquanto psutil é ideal para estimar o consumo total de memória de um método ou execução de função, memory_profiler fornece informações de uso de memória mais detalhadas, incluindo tendências de uso de nível funcional e linear ao longo do tempo.

Para começar, instale memory_profiler em seu ambiente virtual Python. Isso também instala psutil.

pip instalar memory_profiler

Obter o tamanho de um objeto na memória

Você pode iniciar seu perfil de memória calculando primeiro o tamanho de um objeto que pretende usar na memória.

Esse tipo de criação de perfil é útil no início do desenvolvimento — ao tentar determinar qual tipo de objeto usar em um programa.

Por exemplo, se você ficar preso decidindo quais métodos usar para realizar uma tarefa, digamos, o método apropriado Tipo de dados Python, você pode obter o tamanho de cada um em bytes para determinar qual é mais leve para seu uso caso.

O sys.getsizeof método embutido é útil aqui:

importar sistema
imprimir(f"tamanho da lista: {sys.getsizeof([])} bytes")
imprimir(f"tamanho do dicionário: {sys.getsizeof (dict)} bytes")
imprimir(f"tamanho da tupla: {sys.getsizeof(())} bytes")
imprimir(f"tamanho do conjunto: {sys.getsizeof({})} bytes")

Aqui está a saída:

Você também pode usar o sys.getsizeof para comparar o tamanho da memória de uma função integrada e personalizada.

Por exemplo, compare esta função de comprimento personalizado que usa um loop for do Python com o embutido len função:

importar sistema

defgetLength(iterável):
contagem = 0

para eu em iterável:
contar +=1

retornar contar

imprimir(f"Função de comprimento incorporada: {sys.getsizeof (len)} bytes")
imprimir(f"Função de comprimento personalizado: {sys.getsizeof (getLength)} bytes")

O código acima fornece a seguinte saída:

No entanto, enquanto sys.getsizeof mede o tamanho de um objeto na memória, ele considera apenas o próprio objeto e não aqueles que o referenciam. Para isso, você precisará de um método de criação de perfil mais detalhado.

Encontre o perfil de memória de uma função Python

Você pode obter um perfil de memória mais detalhado de cada linha de código de uma função usando o memory_profiler pacote. Isso envolve adicionar o @perfil decorator à sua função ou método:

importar pandas
importar numpy
do perfil de importação do memory_profiler

classe Manipular:
@perfil
def manipularData (self):
df = pandas. Quadro de dados({
'A' :[0, 3, numpy.nan, 10, 3, numpy.nan],
'B': [numpy.nan, "Pandas", numpy.nan, "Pandas", "Python", "JavaScript"],
})

df.fillna (método='bfill', inplace=True)
df.fillna (método='ffill', inplace=True)
retornar str (df)

manip = Manipular()
imprimir (manip.manipulateData())

O código acima fornece um perfil de memória detalhado de cada linha de código na função, conforme mostrado:

O Uso de memória coluna indica o uso de memória para uma determinada linha de código, enquanto o Incremento coluna mostra a sobrecarga contribuída por cada linha. O Ocorrência coluna define o número de vezes que uma linha de código aloca ou desaloca memória.

Por exemplo, na saída acima, a linha 11 ocorreu duas vezes com um incremento de memória de 0,1 MiB (Mebibyte), aumentando o uso de memória para 55,4 MiB. As linhas 19 e 22 também contribuíram com 0,2 MiB e 0,3 MiB, respectivamente, totalizando o uso de memória para 55,9 MiB.

Encontre o perfil de memória de um script Python por timestamp

Você também pode estimar o perfil de memória de um script Python inteiro usando o memory_profiler executando o mprof comando no terminal como mostrado:

mprof execute script_name.py

O comando acima mostra o script especificado a cada 0,1s e cria automaticamente um .dat arquivo dentro do diretório do projeto atual.

As figuras que seguem o MEM notação são os perfis de uso de memória do script Python em um intervalo de tempo específico. Os últimos números à direita representam o registro de data e hora que o criador de perfil capturou para cada uso de memória.

Você também pode obter um gráfico do perfil de memória. Isso requer uma instalação de matplotlib:

pip instalar matplotlib

Uma vez instalado, execute o mprof comando assim:

gráfico mprof

Aqui está a saída neste caso:

Execute o perfil de memória de script em um arquivo Python dedicado

Você pode querer criar um perfil para diferentes scripts Python. Você consegue fazer isso usando um módulo Python dedicado via Python subprocesso.

Dessa forma, você pode separar seu criador de perfil de memória de sua base de código e salvar a saída do gráfico localmente:

importar subprocesso

subprocess.run([
'mprof', 'correr', '--incluir-filhos', 'missing.py'
])

# salva a saída do gráfico localmente
subprocess.run(['mprof', 'trama', '--output=output.jpg'])

Para executar o perfil de memória do script, você só precisa executar o arquivo Python que contém o código acima. Isso gera um gráfico de perfil de memória (output.jpg) no diretório do arquivo:

Encontre a quantidade de memória usada na execução de uma função

Você pode encontrar o perfil de memória total de um método ou função durante a execução usando o psutil pacote.

Por exemplo, para traçar o perfil do anterior Manipulação de DataFrame do Pandas método dentro de outro arquivo Python:

importar psutil
importar sistema
importar os
sys.path.append (sys.path[0] + "/..")

# importe a classe que contém seu método
de somecode.missing importar Manipular

# instancia a classe
manip = Manipular()

processo = psutil. Processo (os.getpid())
initial_memory = process.memory_info().rss

# execute o método de destino:
manip.manipulateData()

# obtém as informações de memória após a execução
final_memory = process.memory_info().rss
memory_consumed = final_memory - initial_memory
memory_consumed_mb = memory_consumed / (1024 * 1024)
imprimir(f"Memória consumida pela função: {memory_consumed_mb:.2f} MB")

O acima estima o perfil de memória total do método em megabytes (MB), conforme mostrado:

Encontre o perfil de memória de uma linha de código no Jupyter Notebook

Se você usar o iPython no Jupyter Notebook, poderá calcular o perfil de memória de uma linha usando o memory_profiler. Você só precisa carregar memory_profiler em uma célula. Em seguida, adicione o %memit função mágica para o seu código nas células subseqüentes; isso retorna a memória de pico do código e o tamanho incrementado.

Este método não funciona com scripts Python regulares além do iPython no Jupyter Notebook.

Por exemplo:

Você também pode usar o %memit função mágica no Jypyter Notebook para criar o perfil da memória de uma função em tempo de execução:

Melhore sua eficiência de memória em seu código Python

Considerando as tarefas pesadas de coleta de dados para as quais costumamos usar o Python, cada linha de código precisa de otimização adequada para gerenciar o uso da memória. Embora o Python apresente muitas funções Python integradas, objetos não referenciados resultam em vazamentos de memória.

Se você tem descartado todas as sintaxes do Python que funcionam em sua base de código sem considerar o uso de memória, convém olhar para trás antes de ir longe demais.