Úvod

Správa paměti je proces efektivního přidělování, odebírání a koordinace paměti tak, aby všechny různé procesy běžely hladce a mohly optimálně přistupovat k různým systémovým prostředkům. Správa paměti také zahrnuje čištění paměti od objektů, ke kterým se již nepřistupuje.

V jazyce Python je za tyto druhy úloh zodpovědný správce paměti, který pravidelně spouští čištění, alokaci a správu paměti. Na rozdíl od jazyků C, Java a dalších programovacích jazyků spravuje Python objekty pomocí počítání referencí. To znamená, že správce paměti sleduje počet referencí na jednotlivé objekty v programu. Když počet referencí objektu klesne na nulu, což znamená, že objekt již není používán, garbage collector (součást správce paměti) automaticky uvolní paměť daného objektu.

Uživatel se nemusí starat o správu paměti, protože proces alokace a dealokace paměti je plně automatický. Znovu získanou paměť mohou využít jiné objekty.

Python Garbage Collection

Jak již bylo vysvětleno, Python odstraňuje objekty, na které se již v programu neodkazuje, aby uvolnil místo v paměti. Tento proces, při kterém Python uvolňuje bloky paměti, které se již nepoužívají, se nazývá Garbage Collection. Garbage Collector (GC) v jazyce Python běží během provádění programu a je spuštěn, pokud se počet referencí sníží na nulu. Počet referencí se zvýší, pokud je objektu přiřazeno nové jméno nebo je umístěn do kontejneru, jako je tuple nebo slovník. Podobně se počet referencí sníží, když je reference na objekt znovu přiřazena, když reference na objekt vyjde z oboru nebo když je objekt odstraněn.

Paměť je halda, která obsahuje objekty a další datové struktury používané v programu. Alokaci a dealokaci tohoto prostoru haldy řídí správce paměti Pythonu pomocí funkcí API.

Objekty v paměti Pythonu

Každá proměnná v Pythonu funguje jako objekt. Objekty mohou být buď jednoduché (obsahující čísla, řetězce atd.), nebo kontejnery (slovníky, seznamy nebo uživatelem definované třídy). Python je navíc dynamicky typovaný jazyk, což znamená, že proměnné ani jejich typy nemusíme před použitím v programu deklarovat.

Příklad:

Podíváte-li se na první dva řádky výše uvedeného programu, je znám objekt x. Když objekt x odstraníme a pokusíme se ho použít, zobrazí se chyba s hlášením, že proměnná x není definována.

Je vidět, že garbage collection v jazyce Python je plně automatizovaný a programátor se o něj nemusí starat, na rozdíl od jazyků jako C.

Modifikace garbage collectoru

Garbage collector v jazyce Python má tři generace, do kterých jsou objekty zařazovány. Nový objekt na začátku svého životního cyklu je první generací garbage collectoru. Jakmile objekt přežije sběr odpadků, bude přesunut do dalších generací. Každá ze tří generací garbage collectoru má svůj práh. Konkrétně, když je překročen práh počtu alokací minus počet de0lokací, spustí se u dané generace garbage collection.

Dřívější generace jsou také garbage collection častěji než vyšší generace. Je to proto, že novější objekty budou s větší pravděpodobností zahozeny než staré objekty.

Modul gc obsahuje funkce pro změnu prahové hodnoty, ruční spuštění procesu garbage collection, vypnutí procesu garbage collection atd. Pomocí metody get_threshold() můžeme zkontrolovat prahové hodnoty různých generací garbage collectoru:

import gcprint(gc.get_threshold())

Ukázkový výstup:

(700, 10, 10)

Jak vidíte, zde máme práh 700 pro první generaci a 10 pro každou z dalších dvou generací.

Můžeme změnit hodnotu prahu pro spuštění procesu sběru odpadu pomocí metody set_threshold() modulu gc:

gc.set_threshold(900, 15, 15)

V uvedeném příkladu jsme zvýšili hodnotu prahu pro všechny 3 generace. Zvýšení prahové hodnoty sníží frekvenci spouštění garbage collectoru. Obvykle se jako vývojáři nemusíme nad sběrem odpadu Pythonu příliš zamýšlet, ale při optimalizaci běhu Pythonu pro cílový systém to může být užitečné. Jednou z hlavních výhod je, že mechanismus sběru smetí v jazyce Python zpracovává mnoho nízkoúrovňových detailů automaticky za vývojáře.

Proč provádět ruční sběr smetí?

Víme, že interpret jazyka Python sleduje reference na objekty použité v programu. V dřívějších verzích jazyka Python (do verze 1.6) používal interpret jazyka Python ke zpracování paměti pouze mechanismus počítání referencí. Když počet referencí klesne na nulu, interpret jazyka Python paměť automaticky uvolní. Tento klasický mechanismus počítání referencí je velmi účinný, až na to, že nefunguje, když má program referenční cykly. K referenčnímu cyklu dochází, pokud se jeden nebo více objektů vzájemně odkazují, a proto počet referencí nikdy nedosáhne nuly.

Uvažujme příklad.

>>> def create_cycle():... list = ... list.append(list)... return list... >>> create_cycle()]

Výše uvedený kód vytváří referenční cyklus, kde objekt list odkazuje sám na sebe. Proto se paměť objektu list po návratu funkce automaticky neuvolní. Problém referenčního cyklu nelze vyřešit počítáním referencí. Problém referenčního cyklu však lze vyřešit změnou chování garbage collectoru v aplikaci Python.

K tomu můžeme použít funkci gc.collect() modulu gc.

import gcn = gc.collect()print("Number of unreachable objects collected by GC:", n)

Funkce gc.collect() vrací počet objektů, které shromáždila a odalokovala.

Existují dva způsoby, jak provádět ruční garbage collection: garbage collection na základě času nebo garbage collection na základě události.

Time-based garbage collection je poměrně jednoduchý: funkce gc.collect() je volána po pevně stanoveném časovém intervalu.

Sběr odpadu založený na událostech volá funkci gc.collect() po výskytu události (tj. když je aplikace ukončena nebo když aplikace zůstane po určitou dobu nečinná).

Pochopíme práci s ručním sběrem odpadu vytvořením několika referenčních cyklů.

Výstup je následující:

Creating garbage...Collecting...Number of unreachable objects collected by GC: 8Uncollectable garbage: 

Výše uvedený skript vytvoří objekt seznamu, na který odkazuje proměnná s kreativním názvem list. První prvek objektu seznamu odkazuje sám na sebe. Počet odkazů na objekt seznamu je vždy větší než nula, i když je v programu smazán nebo mimo obor. Proto objekt list není kvůli kruhové referenci vybírán do koše. Mechanismus garbage collectoru v jazyce Python pravidelně automaticky kontroluje a vybírá kruhové reference.

Ve výše uvedeném kódu, protože počet referencí je alespoň 1 a nikdy nemůže dosáhnout 0, jsme objekty násilně vybrali voláním gc.collect(). Nezapomínejte však na časté vynucování garbage collection. Důvodem je to, že i po uvolnění paměti trvá GC nějakou dobu, než vyhodnotí způsobilost objektu pro garbage collection, což zabírá procesorový čas a prostředky. Nezapomeňte také ručně spravovat garbage collector až po úplném spuštění aplikace.

Závěr

V tomto článku jsme probrali, jak je správa paměti v jazyce Python řešena automaticky pomocí strategií počítání referencí a garbage collection. Bez garbage collection je implementace úspěšného mechanismu správy paměti v jazyce Python nemožná. Programátoři se také nemusí starat o mazání alokované paměti, protože o to se stará správce paměti Pythonu. To vede k menšímu počtu úniků paměti a vyššímu výkonu.

Napsat komentář

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