Introduktion

Minneshantering är processen för att effektivt allokera, ta bort och samordna minne så att alla olika processer fungerar smidigt och kan få optimal tillgång till olika systemresurser. Minneshantering innebär också att rensa minnet från objekt som inte längre nås.

I Python ansvarar minneshanteraren för den här typen av uppgifter genom att regelbundet köra för att rensa, allokera och hantera minnet. Till skillnad från C, Java och andra programmeringsspråk hanterar Python objekt genom att använda referensräkning. Detta innebär att minneshanteraren håller reda på antalet referenser till varje objekt i programmet. När ett objekts referensräkning sjunker till noll, vilket innebär att objektet inte längre används, frigör garbage collector (en del av minneshanteraren) automatiskt minnet från det specifika objektet.

Användaren behöver inte oroa sig för minneshantering eftersom processen med att allokera och de-allokera minne är helt automatisk. Det återvunna minnet kan användas av andra objekt.

Python Garbage Collection

Som förklarats tidigare raderar Python objekt som inte längre refereras i programmet för att frigöra minnesutrymme. Denna process där Python frigör minnesblock som inte längre används kallas Garbage Collection. Pythons Garbage Collector (GC) körs under programmets exekvering och utlöses om referensantalet minskar till noll. Referensantalet ökar om ett objekt tilldelas ett nytt namn eller placeras i en behållare, som tupel eller ordbok. På samma sätt minskar referensantalet när referensen till ett objekt tilldelas på nytt, när objektets referens går utanför räckvidden eller när ett objekt tas bort.

Minnet är en heap som innehåller objekt och andra datastrukturer som används i programmet. Allokeringen och de-allokeringen av detta heaputrymme styrs av Pythons minneshanterare med hjälp av API-funktioner.

Pythonobjekt i minnet

Varje variabel i Python fungerar som ett objekt. Objekt kan antingen vara enkla (innehållande siffror, strängar etc.) eller behållare (ordböcker, listor eller användardefinierade klasser). Python är dessutom ett dynamiskt typat språk, vilket innebär att vi inte behöver deklarera variablerna eller deras typer innan vi använder dem i ett program.

Till exempel:

Om du tittar på de två första raderna i programmet ovan är objektet x känt. När vi tar bort objektet x och försöker använda det får vi ett fel som säger att variabeln x inte är definierad.

Du kan se att skräpinsamlingen i Python är helt automatiserad och programmeraren behöver inte oroa sig för den, till skillnad från språk som C.

Modifiera skräpinsamlaren

Pythons skräpinsamlare har tre generationer i vilka objekt klassificeras. Ett nytt objekt i början av sin livscykel är den första generationen av garbage collector. Allteftersom objektet överlever sopkollektionen flyttas det upp till nästa generationer. Var och en av skräpplockarens tre generationer har ett tröskelvärde. När tröskelvärdet för antalet allokeringar minus antalet de0allokeringar överskrids kommer den generationen att köra skräpplockning.

Förre generationer skräpplockas också oftare än de högre generationerna. Detta beror på att nyare objekt har större sannolikhet att kasseras än gamla objekt.

Modulen gc innehåller funktioner för att ändra tröskelvärdet, utlösa en skräpplockningsprocess manuellt, inaktivera skräpplockningsprocessen osv. Vi kan kontrollera tröskelvärdena för olika generationer av skräpplockaren med hjälp av metoden get_threshold():

import gcprint(gc.get_threshold())

Sampelutgång:

(700, 10, 10)

Som du ser har vi här ett tröskelvärde på 700 för den första generationen och 10 för var och en av de andra två generationerna.

Vi kan ändra tröskelvärdet för att utlösa skräpplockningsprocessen med hjälp av set_threshold()-metoden i gc-modulen:

gc.set_threshold(900, 15, 15)

I exemplet ovan har vi ökat tröskelvärdet för alla tre generationerna. Om tröskelvärdet ökas minskar frekvensen för körning av skräpplockaren. Normalt behöver vi inte tänka så mycket på Pythons garbage collection som utvecklare, men detta kan vara användbart när du optimerar Pythons körtid för ditt målsystem. En av de viktigaste fördelarna är att Pythons garbage collection-mekanism hanterar många detaljer på låg nivå för utvecklaren automatiskt.

Varför utföra manuell garbage collection?

Vi vet att Python-tolken håller reda på referenser till objekt som används i ett program. I tidigare versioner av Python (fram till version 1.6) använde Python-tolken endast referensräkningsmekanismen för att hantera minnet. När referensräkningen sjunker till noll frigör Pythontolken automatiskt minnet. Denna klassiska referensräkningsmekanism är mycket effektiv, förutom att den inte fungerar när programmet har referenscykler. En referenscykel uppstår om ett eller flera objekt refererar till varandra, och därför når referensräkningen aldrig noll.

Låt oss ta ett exempel.

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

Ovanstående kod skapar en referenscykel, där objektet list refererar till sig självt. Därför kommer minnet för objektet list inte att frigöras automatiskt när funktionen återvänder. Problemet med referenscykeln kan inte lösas med hjälp av referensräkning. Detta referenscykelproblem kan dock lösas genom att ändra garbage collectors beteende i din Python-applikation.

För att göra detta kan vi använda funktionen gc.collect() i modulen gc.

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

Den gc.collect() returnerar antalet objekt som den har samlat in och avallokerat.

Det finns två sätt att utföra manuell sophämtning: tidsbaserad eller händelsebaserad sophämtning.

Tidsbaserad sophämtning är ganska enkel: gc.collect()-funktionen anropas efter ett fast tidsintervall.

Händelsebaserad skräpplockning anropar gc.collect()-funktionen efter att en händelse inträffar (dvs. när programmet avslutas eller när programmet förblir inaktivt under en viss tidsperiod).

Låt oss förstå hur den manuella skräpplockningen fungerar genom att skapa några referenscykler.

Utfallet ser ut som nedan:

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

Skriptet ovan skapar ett listobjekt som refereras av en variabel med det kreativa namnet list. Det första elementet i listobjektet hänvisar till sig självt. Referensantalet för listobjektet är alltid större än noll även om det tas bort eller hamnar utanför räckvidden i programmet. Därför samlas list-objektet inte in i soporna på grund av den cirkulära referensen. Garbage Collector-mekanismen i Python kommer automatiskt att kontrollera och samla in cirkulära referenser med jämna mellanrum.

I koden ovan har vi, eftersom referensantalet är minst 1 och aldrig kan nå 0, tvingat fram en garbage collection av objekten genom att anropa gc.collect(). Kom dock ihåg att inte tvinga fram garbage collection ofta. Anledningen är att även efter att minnet har frigjorts tar GC tid på sig att utvärdera om objektet är berättigat till skräpplockning, vilket tar processortid och resurser i anspråk. Kom också ihåg att manuellt hantera garbage collector först när din app har startat helt.

Slutsats

I den här artikeln diskuterade vi hur minneshantering i Python hanteras automatiskt med hjälp av strategier för referensräkning och garbage collection. Utan garbage collection är det omöjligt att implementera en framgångsrik minneshanteringsmekanism i Python. Programmerare behöver inte heller oroa sig för att radera allokerat minne, eftersom det tas om hand av Pythons minneshanterare. Detta leder till färre minnesläckor och bättre prestanda.

Lämna ett svar

Din e-postadress kommer inte publiceras.