Hunting for Memory Leaks in Python applications

Wai Chee Yau

Follow

13 feb, 2019 – 4 min read

We gebruiken Python redelijk veel bij Zendesk voor het bouwen van machine learning (ML) producten. Een van de meest voorkomende prestatieproblemen die we tegenkomen bij machine learning-toepassingen zijn geheugenlekken en pieken. De Python-code wordt meestal uitgevoerd in containers via gedistribueerde verwerkingsframeworks zoals Hadoop, Spark en AWS Batch. Elke container krijgt een vaste hoeveelheid geheugen toegewezen. Zodra de uitvoering van de code de gespecificeerde geheugenlimiet overschrijdt, wordt de container beëindigd als gevolg van out of memory errors.

Een snelle oplossing is om de geheugentoewijzing te verhogen. Dit kan echter leiden tot verspilling van middelen en invloed hebben op de stabiliteit van de producten als gevolg van onvoorspelbare geheugen pieken. De oorzaken van geheugenlekken kunnen onder meer zijn:

  • het plaatsen van grote objecten die niet worden vrijgegeven
  • referentiecycli binnen de code
  • onderliggende bibliotheken/C-extensies die geheugen lekken

Een nuttige oefening is om het geheugengebruik van de toepassingen te profileren om een beter inzicht te krijgen in de ruimte-efficiëntie van de code en de onderliggende pakketten die worden gebruikt. Deze post behandelt:

  • profilering geheugengebruik van de toepassing in de tijd
  • hoe het geheugengebruik te inspecteren op een specifiek deel van het programma
  • tips voor het debuggen van geheugenproblemen

U kunt kijken naar het geheugengebruik variërend in de tijd tijdens de uitvoering van de Python-code met behulp van het memory-profile pakket.

# install the required packages
pip install memory_profiler
pip install matplotlib# run the profiler to record the memory usage
# sample 0.1s by defaut
mprof run --include-children python fantastic_model_building_code.py# plot the recorded memory usage
mprof plot --output memory-profile.png

A. Geheugenprofiel als functie van de tijd

Met de optie include-children wordt ook het geheugengebruik berekend van eventuele kindprocessen die via het ouderproces tot stand zijn gekomen. Grafiek A toont een iteratief modeltrainingsproces waarbij het geheugen in cycli toeneemt naarmate er batches met trainingsgegevens worden verwerkt. De objecten worden vrijgegeven zodra de vuilnisophaal wordt gestart.

Als het geheugengebruik constant toeneemt, is er een potentieel probleem van geheugenlekken. Hier volgt een voorbeeldscript om dit te illustreren.

B. Geheugengebruik neemt in de loop van de tijd toe

Een debugger-breekpunt kan worden ingesteld zodra het geheugengebruik een bepaalde drempel overschrijdt met de optie pdb-mmem, wat handig is voor het oplossen van problemen.

Geheugendump op een bepaald moment

Het is belangrijk om inzicht te krijgen in het verwachte aantal grote objecten in het programma en of deze moeten worden gedupliceerd en/of getransformeerd naar verschillende formaten.

Om de objecten in het geheugen verder te analyseren, kan een heapdump worden gemaakt tijdens bepaalde regels van de code in het programma met muppy.

Voorbeeld van samenvatting van heap dump van het geheugen

Een andere nuttige bibliotheek voor geheugenprofilering is objgraph, waarmee objectgrafieken kunnen worden gegenereerd om de lijn van objecten te inspecteren.

Streef naar een snelle feedbacklus

Een nuttige aanpak is het maken van een kleine “testcase” die alleen de geheugenlekkende code in kwestie uitvoert. Overweeg het gebruik van een subset van de willekeurig bemonsterde gegevens als het lang duurt om de volledige invoergegevens uit te voeren.

Run geheugenintensieve taken in een apart proces

Python geeft niet noodzakelijkerwijs geheugen onmiddellijk terug aan het besturingssysteem. Om er zeker van te zijn dat geheugen wordt vrijgegeven nadat een stuk code is uitgevoerd, moet het in een apart proces worden uitgevoerd. Deze pagina geeft meer details over Python garbage collection.

Debugger kan verwijzingen naar objecten toevoegen

Als een breakpoint debugger zoals pdb wordt gebruikt, zullen alle objecten die zijn gemaakt en waarnaar handmatig wordt verwezen vanuit de debugger, in het geheugenprofiel blijven staan. Dit kan een vals gevoel van geheugenlekken geven, waarbij objecten niet op tijd worden vrijgegeven.

Waarschuw pakketten die lek kunnen zijn

Sommige Python bibliotheken kunnen mogelijk geheugenlekken hebben. Bijv. pandas heeft nogal wat bekende problemen met geheugenlekken.

Happy hunting!

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.