Eu tenho um script de execução longa que, se for executado por tempo suficiente, consumirá toda a memória do meu sistema.
Sem entrar em detalhes sobre o script, tenho duas perguntas:
- Existem algumas "práticas recomendadas" a serem seguidas, que ajudarão a impedir a ocorrência de vazamentos?
- Quais técnicas existem para depurar vazamentos de memória no Python?
python
debugging
memory-management
memory-leaks
Fragsworth
fonte
fonte
__del__
método que não são mais referenciados, exceto pelo ciclo. O ciclo não pode ser interrompido devido a problemas com__del__
. Consertá-lo!Respostas:
Veja este artigo: Rastreando vazamentos de memória python
Além disso, observe que o módulo de coleta de lixo pode realmente ter sinalizadores de depuração definidos. Veja a
set_debug
função. Além disso, observe este código do Gnibbler para determinar os tipos de objetos que foram criados após uma chamada.fonte
Experimentei a maioria das opções mencionadas anteriormente, mas achei este pacote pequeno e intuitivo o melhor: pympler
É bastante simples rastrear objetos que não foram coletados pelo lixo, veja este pequeno exemplo:
instalar pacote via
pip install pympler
A saída mostra todos os objetos que foram adicionados, além da memória que consumiram.
Saída de amostra:
Este pacote fornece vários outros recursos. Verifique a documentação do pympler , em particular a seção Identificando vazamentos de memória .
fonte
pympler
pode ser lento . Se você estiver fazendo algo semi-em tempo real, isso pode prejudicar completamente o desempenho do aplicativo.Deixe-me recomendar a ferramenta mem_top que eu criei
Isso me ajudou a resolver um problema semelhante
Ele mostra instantaneamente os principais suspeitos por vazamento de memória em um programa Python
fonte
O módulo Tracemalloc foi integrado como um módulo interno a partir do Python 3.4 e, aparentemente, também está disponível para versões anteriores do Python como uma biblioteca de terceiros (ainda não o testamos).
Este módulo é capaz de produzir os arquivos e linhas precisos que alocaram mais memória. IMHO, essas informações são infinitamente mais valiosas do que o número de instâncias alocadas para cada tipo (o que acaba sendo muitas tuplas 99% do tempo, o que é uma pista, mas dificilmente ajuda na maioria dos casos).
Eu recomendo que você use tracemalloc em combinação com pyrasite . 9 em 10, executar o snippet dos 10 melhores em um shell de pyrasite fornecerá informações e dicas suficientes para corrigir o vazamento em 10 minutos. No entanto, se você ainda não conseguir encontrar a causa do vazamento, o pyrasite-shell em combinação com as outras ferramentas mencionadas neste tópico provavelmente também fornecerá mais algumas dicas. Você também deve dar uma olhada em todos os auxiliares extras fornecidos pelo pyrasite (como o visualizador de memória).
fonte
Você deve observar especialmente seus dados globais ou estáticos (dados de longa duração).
Quando esses dados crescem sem restrição, você também pode obter problemas no Python.
O coletor de lixo só pode coletar dados, que não são mais referenciados. Mas seus dados estáticos podem conectar elementos de dados que devem ser liberados.
Outro problema pode ser os ciclos de memória, mas pelo menos em teoria o coletor de lixo deve encontrar e eliminar ciclos - pelo menos enquanto não estiverem conectados a alguns dados de longa duração.
Que tipos de dados de vida longa são especialmente problemáticos? Dê uma boa olhada em todas as listas e dicionários - eles podem crescer sem limite. Nos dicionários, você pode até não perceber o problema, pois quando você acessa os ditados, o número de chaves no dicionário pode não ter grande visibilidade para você ...
fonte
Para detectar e localizar vazamentos de memória para processos de execução longa, por exemplo, em ambientes de produção, agora você pode usar o stackimpact . Ele usa tracemalloc embaixo. Mais informações neste post .
fonte
Quanto às melhores práticas, fique de olho nas funções recursivas. No meu caso, tive problemas com recursão (onde não era necessário). Um exemplo simplificado do que eu estava fazendo:
operar dessa maneira recursiva não acionará a coleta de lixo e limpará os restos da função; portanto, toda vez que o uso da memória estiver crescendo, cada vez mais.
Minha solução foi extrair a chamada recursiva de my_function () e ter o main () quando deveria chamá-la novamente. dessa forma, a função termina naturalmente e limpa depois de si mesma.
fonte
Não tenho certeza sobre "Boas práticas" para vazamentos de memória em python, mas o python deve limpar sua própria memória pelo coletor de lixo. Então, principalmente, eu começaria verificando uma lista circular de alguns curtos, pois eles não serão recolhidos pelo coletor de lixo.
fonte
Este não é um conselho exaustivo. Porém, o número um a ter em mente ao escrever com o objetivo de evitar vazamentos de memória no futuro (loops) é garantir que qualquer coisa que aceite uma referência a um retorno de chamada, armazene esse retorno como uma referência fraca.
fonte