Recentemente, me interessei por algoritmos e comecei a explorá-los escrevendo uma implementação ingênua e otimizando-a de várias maneiras.
Eu já estou familiarizado com o módulo Python padrão para criação de perfil em tempo de execução (para a maioria das coisas, achei a função mágica timeit no IPython suficiente), mas também estou interessado no uso de memória para poder explorar essas vantagens também ( por exemplo, o custo de armazenar em cache uma tabela de valores calculados anteriormente versus recalculá-los conforme necessário). Existe um módulo que analise o uso de memória de uma determinada função para mim?
Respostas:
Este já foi respondido aqui: Python memory profiler
Basicamente, você faz algo assim (citado em Guppy-PE ):
fonte
Python 3.4 inclui um novo módulo:
tracemalloc
. Ele fornece estatísticas detalhadas sobre qual código está alocando mais memória. Aqui está um exemplo que exibe as três principais linhas que alocam memória.E aqui estão os resultados:
Quando um vazamento de memória não é um vazamento?
Esse exemplo é ótimo quando a memória ainda está sendo mantida no final do cálculo, mas às vezes você tem um código que aloca muita memória e libera tudo. Tecnicamente, não é um vazamento de memória, mas está usando mais memória do que você imagina. Como você pode rastrear o uso da memória quando tudo é lançado? Se for o seu código, você provavelmente poderá adicionar algum código de depuração para tirar instantâneos enquanto estiver em execução. Caso contrário, você pode iniciar um thread em segundo plano para monitorar o uso da memória enquanto o thread principal é executado.
Aqui está o exemplo anterior, onde todo o código foi movido para a
count_prefixes()
função Quando essa função retorna, toda a memória é liberada. Também adicionei algumassleep()
chamadas para simular um cálculo de longa duração.Quando executo essa versão, o uso de memória diminuiu de 6 MB para 4KB, porque a função liberou toda a memória ao terminar.
Agora, aqui está uma versão inspirada em outra resposta que inicia um segundo thread para monitorar o uso da memória.
O
resource
módulo permite verificar o uso atual da memória e salvar o instantâneo do pico de uso da memória. A fila permite que o thread principal informe ao thread do monitor de memória quando imprimir seu relatório e desligar. Quando executado, mostra a memória que está sendo usada pelalist()
chamada:Se você estiver no Linux, poderá achar
/proc/self/statm
mais útil que oresource
módulo.fonte
long_running()
dentro dacount_prefixes()
função, os valores máximos de RSS não serão impressos até quelong_running()
retorne. Ou estou enganado?memory_monitor()
está sendo executado em um encadeamento separadocount_prefixes()
, portanto, as únicas maneiras pelas quais um pode afetar o outro são o GIL e a fila de mensagens para as quais passomemory_monitor()
. Eu suspeito que, quandocount_prefixes()
chamadassleep()
, isso incentiva o contexto do thread a alternar. Se vocêlong_running()
não estiver demorando muito, o contexto do encadeamento poderá não ser alterado até vocêsleep()
retornar a chamadacount_prefixes()
. Se isso não fizer sentido, poste uma nova pergunta e vincule-a aqui.Se você deseja apenas examinar o uso de memória de um objeto, ( responda a outra pergunta )
fonte
asizeof
asizeof
pode contribuir para o RSS, sim. Não sei ao certo o que você quer dizer com "relacionado a".tracemalloc
solução abaixo de uma magnitude mais rápidoDivulgação:
Mas legal por causa de sua simplicidade:
Basta inserir
using("Label")
onde deseja ver o que está acontecendo. Por exemplofonte
usage[2]
você está olhandoru_maxrss
, é apenas a parte do processo que é residente . Isso não ajudará muito se o processo tiver sido trocado para o disco, mesmo que parcialmente.resource
é um módulo específico do Unix que não funciona no Windows.ru_maxrss
(ou seja,usage[2]
) são kB, não páginas, portanto não há necessidade de multiplicar esse número porresource.getpagesize()
.Como a resposta aceita e também a próxima resposta mais votada têm, na minha opinião, alguns problemas, gostaria de oferecer mais uma resposta que se baseia estreitamente na resposta de Ihor B. com algumas pequenas mas importantes modificações.
Essa solução permite executar a criação de perfil , envolvendo uma chamada de função com a
profile
função e chamando-a ou decorando sua função / método com o@profile
decorador.A primeira técnica é útil quando você deseja criar um perfil de código de terceiros sem mexer com sua fonte, enquanto a segunda técnica é um pouco "mais limpa" e funciona melhor quando você não se importa de modificar a fonte da função / método que você deseja criar um perfil.
Também modifiquei a saída para obter RSS, VMS e memória compartilhada. Eu não me importo muito com os valores "antes" e "depois", mas apenas com o delta, então os removi (se você estiver comparando com a resposta de Ihor B.).
Código de criação de perfil
Exemplo de uso, supondo que o código acima seja salvo como
profile.py
:Isso deve resultar em uma saída semelhante à abaixo:
Algumas notas finais importantes:
profile(my_function, arg)
criar um perfilmy_function(arg)
fonte
Abaixo está um simples decorador de funções que permite rastrear quanta memória o processo consumiu antes da chamada da função, após a chamada da função e qual é a diferença:
Aqui está o meu blog que descreve todos os detalhes. ( link arquivado )
fonte
process.memory_info().rss
nãoprocess.get_memory_info().rss
, pelo menos em ubuntu e pitão 3,6. stackoverflow.com/questions/41012058/psutil-error-on-macostalvez ajude:
< veja mais >
fonte
fonte