Kada se različiti softverski programi pokreću i izvršavaju, mogu akumulirati različite podatkovne objekte koji nisu od posebne koristi. Ovi, nepotrebni objekti poznati kao smeće u računalnom doslovnom smislu, jednostavno jedu memorijski prostor i zauzvrat ometaju performanse. Dakle, sakupljanje smeća (GC) je proces ili način čišćenja nepotrebnih objekata. Stoga se ovaj post ovdje bavi mehanikom sakupljanja smeća u Pythonu.
Zapravo, Piton nudi mnogo fleksibilnosti. Kako se nosi s tim smećem. Uključuje izvornu podršku za ručno i automatsko prikupljanje smeća. Dakle, što čekamo? Idemo dalje!!!
Upravljanje memorijskim prostorom
Upravljanje memorijskim prostorom je proces kojim se upravlja memorijskim prostorom tijekom procesa čitanja i pisanja. Upravitelj memorije je onaj koji određuje memorijsku lokaciju za podatkovne objekte. Sam proces dodjele ili pružanja memorijskih prostora naziva se memorijom dodjela.
Sada zaronimo dublje. U našim sustavima postoji fizički uređaj poznat kao tvrdi disk za pohranu podataka. Pohranjuje podatke koji dolaze iz raznih programa i izvršenja. Python kod ima različite slojeve apstrakcije. Operacijski sustav (OS) izvršava različite zahtjeve za čitanje i pisanje memorije.
Povrh operativnog sustava postoje neke posebne aplikacije. Upravljanjem memorijom za Python kod upravlja aplikacija Python Implementation. Postoje različiti algoritmi i druge strukture koje Python koristi za upravljanje memorijom.
Skupljanje smeća
Kao što smo već vidjeli, sakupljanje smeća je proces čišćenja ili rukovanja raznim nepotrebnim predmetima.
Stoga zahtijeva naprednu i sustavnu implementaciju za inteligentno upravljanje memorijskim prostorom. Budući da nakupljanje neželjenih podatkovnih objekata tijekom vremena rezultira lošim performansama sustava. Ovaj problem je ono što je poznato kao curenje memorije.
Različite metode kao što su praćenje, brojanje referenci, vremenska oznaka i analiza izlaza koriste se u procesu skupljanja smeća. Ove metode mogu se integrirati u sustave prevoditelja i runtime različitih programskih jezika. Ipak, Python koristi tehniku brojanja referenci.
Rad skupljanja smeća u Pythonu
Pythonova postavka sakupljanja smeća prvenstveno koristi metodu brojanja referenci. Koristi broj referenci objekta kako bi odredio treba li ga izbrisati ili ne.
Brojanje referenci
Svaki objekt ili varijabla u vašem Python kodu prati se koliko je puta referenciran. Ovaj broj referenci raste kad god se varijabla referencira i smanjuje kad god se dereferencira. Nakon što ovaj broj dosegne 0, Python rado briše tu varijablu iz memorije vašeg sustava. Zatim vraća blokove koji su bili zadržani zbog varijable. Dobivamo pristup broju referenci objekta pomoću funkcije sys.getrefcount(). Poigrajmo se s tim koristeći Python Shell u našem terminalu.
>>> import sys >>> phrase = "Hello world!" >>> sys.getrefcount(phrase) 2
Broj referenci ovdje je 2. Zašto? Zbog toga što se varijabla “fraza” prosljeđuje u “getrefcount” zauzvrat se računa kao referenca.
Pogledajmo još neke primjere:
>>> arr = [] >>> arr.append(phrase) >>> sys.getrefcount(phrase) 3 >>> dict = {} >>> dict['phrase'] = phrase >>> sys.getrefcount(phrase) 4
Ovdje vidimo da se broj referenci povećava jer se dodaje nizu i rječniku.
Sada, pogledajmo učinak dereferenciranja kroz primjer.
>>> arr = [] # resetting the array >>> sys.getrefcount(phrase) 3 >>> dict['phrase'] = "My name is Shubham" >>> sys.getrefcount(phrase) 2
Ako želite raditi ili znate o Magic Methods, dođite ovdje…
Referentni ciklus
Ovdje smo vidjeli da kada broj referenci objekta postane 0, Python ga briše iz memorije. Međutim, u nekim posebnim slučajevima gdje su objektima dodijeljene vrijednosti, broj referenci možda nikada neće postati 0. Što ćemo u tom slučaju? Moramo ga eksplicitno izbrisati iz memorije. To je ono što je poznato kao referentni ciklus.
Pogledajmo neke primjere:
>>> arr = ['Shubham', 'Rakshit', 'Manya'] >>> arr ['Shubham', 'Rakshit', 'Manya'] >>> arr.append(arr) >>> arr ['Shubham', 'Rakshit', 'Manya', ['Shubham', 'Rakshit', 'Manya']]
>>> class ownClass: ... pass ... >>> Obj = ownClass() >>> Obj.my_prop = Obj
Ovo je jedna situacija u kojoj broj referenci nikada neće dosegnuti 0, jer se referira na sebe. Pogledajmo situaciju u kojoj postoji veći broj podatkovnih objekata koji se referenciraju jedni na druge.
>>> dict1 = {} >>> dict2 = {} >>> dict1['dict2'] = dict2 >>> dict2['dict1'] = dict1
Budući da se vidi da oba objekta referenciraju jedan na drugog, uvijek će biti najmanji broj referenci 1. Pogledajmo jedan vrlo pametan hack ovdje:
>>> import ctypes # it allows access to an object from memory even if deleted >>> class myObject(ctypes.Structure): _fields_ = [("refcnt", ctypes.c_long)] >>> dict1 = {} >>>dict2 = {} >>> dict1['dict2'] = dict2 >>> dict2['dict1'] = dict1 >>> address_obj = id(dict1) # getting the memory address >>> address_obj 140730947711232 >>> del dict1, dict2 # deleting both objects >>> print(myObject.from_address(address_obj).refcnt) 1
Modul gc() — još jedan način za sakupljanje smeća u Pythonu
>>> import gc >>> import ctypes >>> class myObject(ctypes.Structure): _fields_ = [("refcnt", ctypes.c_long)] >>> dict1 = {} >>>dict2 = {} >>> dict1['dict2'] = dict2 >>> dict2['dict1'] = dict1 >>> collection = gc.collect() >>> print("Values : collection {} objects.".format(collection)) Values : collection 0 objects. >>> address_obj = id(dict1) # getting the memory address >>> address_obj 140730947711232 >>> del dict1, dict2 # deleting both objects >>> print(myObject.from_address(address_obj).refcnt) 1 >>> collection = gc.collect() >>> print("Values : collection {} objects.".format(collection)) Values : collection 2 objects. >>> print(myObject.from_address(address_obj).refcnt) 0 # its the reference count when the gc is called
Metoda brojanja referenci u Pythonu je automatska. To se događa u stvarnom vremenu. Dok su operacije odvoza smeća generacijski periodične. Provjerimo što ćemo još postići koristeći gc modul.
>>> import gc >>> gc.get_threshold() (800, 15, 15)
Pogledajmo ukupan broj podatkovnih objekata koji se trenutno nalaze u memoriji pomoću “gc.get_count()” .
>>> gc.get_count() (788, 19, 0)
Kao što vidimo u gornjim primjerima, broj objekata prve generacije je 788. To je prilično veliko, zar ne? Hajdemo sada ručno pozvati kolekciju i vidjeti razliku koja to čini.
>>> gc.collect() 0 >>> gc.get_count() (35, 0, 0)
Broj se sada smanjio na 35 s prethodne vrijednosti od 788. Prilično velika razlika!
Sada ručno promijenimo vrijednosti praga.
>>> gc.set_threshold(900,25,25) >>> gc.get_threshold() (900,25,25)
ZAVRŠNE RIJEČI
U ovom smo postu naišli na to što je odvoz smeća? Zatim smo odatle prešli na temu upravljanja memorijskim prostorom. Dakle, vratili smo se kako bismo dobili čist, dubinski pogled na koncept skupljanja smeća. Zatim smo krenuli dalje da vidimo kako metoda skupljanja smeća radi u Pythonu. Koje su razne funkcije i moduli povezani s ovim zadatkom. Vidjeli smo i neke hakove. Sve smo to vidjeli uz pomoć prilično puno nevjerojatnih hakova i primjera znanja.
Stoga sam dao sve od sebe da vam razjasnim ovu temu. Ali, u svakom slučaju, još uvijek imate neke sumnje. Zatim mi, molim vas, pišite u odjeljku za komentare i ja sam kao i uvijek uvijek spreman pomoći vam. I također riješite svoje upite i probleme.