Lovení úniků paměti v aplikacích Python

Wai Chee Yau

Sledovat

13. února, 2019 – 4 minuty čtení

V Zendesku používáme Python poměrně často pro vytváření produktů strojového učení (ML). Jedním z běžných výkonnostních problémů, se kterými jsme se u aplikací strojového učení setkali, jsou úniky paměti a výkyvy. Kód v jazyce Python se obvykle spouští v kontejnerech prostřednictvím rámců pro distribuované zpracování, jako jsou Hadoop, Spark a AWS Batch. Každému kontejneru je přiděleno pevné množství paměti. Jakmile provádění kódu překročí stanovený paměťový limit, kontejner se ukončí kvůli chybám při nedostatku paměti.

Rychlým řešením je zvýšení přidělené paměti. To však může vést k plýtvání prostředky a ovlivnit stabilitu produktů kvůli nepředvídatelným výkyvům paměti. Mezi příčiny úniků paměti mohou patřit:

  • předávání velkých objektů, které nejsou uvolněny
  • referenční cykly v kódu
  • podložené knihovny/rozšíření, z nichž uniká paměť

Užitečným cvičením je profilování využití paměti aplikací pro lepší pochopení prostorové efektivity kódu a použitých podkladových balíčků. Tento příspěvek se zabývá:

  • profilováním využití paměti aplikace v čase
  • jak zkontrolovat využití paměti v určité části programu
  • tipem pro ladění problémů s pamětí

Pomocí balíčku memory-profile se můžete podívat na využití paměti měnící se v čase během provádění kódu Pythonu.

# 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. Paměťový profil jako funkce času

Volba include-children zahrne využití paměti všech podřízených procesů spuštěných prostřednictvím rodičovského procesu. Graf A ukazuje iterativní proces trénování modelu, který způsobuje nárůst paměti v cyklech podle toho, jak se zpracovávají dávky trénovacích dat. Objekty jsou uvolněny, jakmile se spustí garbage collection.

Pokud využití paměti neustále roste, existuje potenciální problém úniku paměti. Zde je fiktivní ukázkový skript, který to ilustruje.

B. Paměťové stopy rostoucí v čase

Pomocí volby pdb-mmem lze nastavit bod přerušení debuggeru, jakmile využití paměti překročí určitou mez, což se hodí při řešení problémů.

Výpis paměti v určitém okamžiku

Důležité je pochopit očekávaný počet velkých objektů v programu a to, zda by měly být duplikovány a/nebo transformovány do jiných formátů.

Pro další analýzu objektů v paměti lze vytvořit výpis haldy během určitých řádků kódu v programu pomocí muppy.

Příklad shrnutí výpisu haldy paměti

Další užitečnou knihovnou pro profilování paměti je objgraph, která umí vytvářet grafy objektů a kontrolovat jejich linii.

Snažte se o rychlou zpětnou vazbu

Užitečným přístupem je vytvoření malého „testovacího případu“, který spustí pouze daný kód s únikem paměti. Zvažte použití podmnožiny náhodně vybraných dat, pokud je spuštění kompletních vstupních dat zdlouhavé.

Spustit úlohy náročné na paměť v samostatném procesu

Python nemusí nutně uvolnit paměť okamžitě zpět do operačního systému. Aby bylo zajištěno uvolnění paměti po vykonání části kódu, je třeba ji spustit v samostatném procesu. Na této stránce naleznete další podrobnosti o garbage collection v jazyce Python.

Debugger může přidávat odkazy na objekty

Pokud je použit debugger s breakpointem, například pdb, zůstanou všechny objekty vytvořené a odkazované ručně z debuggeru v profilu paměti. To může vyvolat falešný pocit úniku paměti, kdy objekty nejsou včas uvolněny.

Dejte si pozor na balíčky, které mohou být děravé

U některých knihoven Pythonu může potenciálně docházet k únikům paměti. Např. pandas má poměrně dost známých problémů s úniky paměti.

Šťastný lov!

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.