Wprowadzenie

Zarządzanie pamięcią to proces efektywnego przydzielania, odbierania i koordynowania pamięci, aby wszystkie różne procesy działały płynnie i mogły optymalnie korzystać z różnych zasobów systemowych. Zarządzanie pamięcią polega również na czyszczeniu pamięci z obiektów, do których nie ma już dostępu.

W Pythonie menedżer pamięci jest odpowiedzialny za tego rodzaju zadania, okresowo uruchamiając się w celu oczyszczenia, przydzielenia i zarządzania pamięcią. W przeciwieństwie do C, Javy i innych języków programowania, Python zarządza obiektami za pomocą liczenia referencji. Oznacza to, że menedżer pamięci śledzi liczbę referencji do każdego obiektu w programie. Gdy liczba referencji obiektu spada do zera, co oznacza, że obiekt nie jest już używany, garbage collector (część menedżera pamięci) automatycznie zwalnia pamięć z tego konkretnego obiektu.

Użytkownik nie musi się martwić o zarządzanie pamięcią, ponieważ proces alokacji i de-alokacji pamięci jest w pełni automatyczny. Odzyskana pamięć może być wykorzystana przez inne obiekty.

Python Garbage Collection

Jak wyjaśniono wcześniej, Python usuwa obiekty, które nie są już przywoływane w programie, aby zwolnić miejsce w pamięci. Ten proces, w którym Python zwalnia bloki pamięci, które nie są już używane, nazywany jest Garbage Collection. Garbage Collector (GC) Pythona działa podczas wykonywania programu i jest uruchamiany, gdy liczba referencji spadnie do zera. Liczba referencji wzrasta, jeśli obiektowi zostanie nadana nowa nazwa lub zostanie on umieszczony w kontenerze, takim jak tuple lub słownik. Podobnie, liczba referencji maleje, gdy referencja do obiektu jest ponownie przypisywana, gdy referencja obiektu wychodzi poza zakres lub gdy obiekt jest usuwany.

Pamięć jest stertą, która zawiera obiekty i inne struktury danych używane w programie. Alokacja i de-alokacja tej przestrzeni sterty jest kontrolowana przez menedżera pamięci Pythona za pomocą funkcji API.

Obiekty Pythona w pamięci

Każda zmienna w Pythonie działa jak obiekt. Obiekty mogą być albo proste (zawierające liczby, ciągi znaków itp.) albo kontenery (słowniki, listy lub klasy zdefiniowane przez użytkownika). Ponadto Python jest językiem dynamicznie typowanym, co oznacza, że nie musimy deklarować zmiennych ani ich typów przed użyciem ich w programie.

Na przykład:

Jeśli spojrzysz na pierwsze 2 wiersze powyższego programu, obiekt x jest znany. Gdy usuniemy obiekt x i spróbujemy go użyć, otrzymamy błąd informujący, że zmienna x nie jest zdefiniowana.

Widzisz, że odśmiecanie w Pythonie jest w pełni zautomatyzowane i programista nie musi się o nie martwić, w przeciwieństwie do języków takich jak C.

Modyfikowanie garbage collectora

Garbage collector Pythona ma trzy generacje, w których obiekty są klasyfikowane. Nowy obiekt w początkowym punkcie swojego cyklu życia jest pierwszą generacją garbage collectora. Gdy obiekt przeżyje odśmiecanie, zostanie przeniesiony do następnych generacji. Każda z 3 generacji garbage collectora ma swój próg. Konkretnie, po przekroczeniu progu liczby alokacji minus liczba de0alokacji, generacja ta uruchomi odśmiecanie.

Wcześniejsze generacje są również odśmiecane częściej niż generacje wyższe. Dzieje się tak, ponieważ nowsze obiekty są bardziej narażone na wyrzucenie niż stare.

Moduł gc zawiera funkcje umożliwiające zmianę wartości progowej, ręczne wyzwalanie procesu odśmiecania, wyłączanie procesu odśmiecania itp. Możemy sprawdzić wartości progowe różnych generacji garbage collectora, korzystając z metody get_threshold():

import gcprint(gc.get_threshold())

Przykładowe dane wyjściowe:

(700, 10, 10)

Jak widać, tutaj mamy próg 700 dla pierwszej generacji i 10 dla każdej z pozostałych dwóch generacji.

Możemy zmienić wartość progu wyzwalającego proces odśmiecania, używając metody set_threshold() modułu gc:

gc.set_threshold(900, 15, 15)

W powyższym przykładzie zwiększyliśmy wartość progu dla wszystkich 3 generacji. Zwiększenie wartości progu spowoduje zmniejszenie częstotliwości uruchamiania garbage collectora. Zwykle nie musimy zbyt wiele myśleć o odśmiecaniu Pythona jako programista, ale może to być przydatne podczas optymalizacji runtime Pythona dla systemu docelowego. Jedną z kluczowych korzyści jest to, że mechanizm odśmiecania Pythona automatycznie obsługuje wiele niskopoziomowych szczegółów dla programisty.

Why Perform Manual Garbage Collection?

Wiemy, że interpreter Pythona śledzi odniesienia do obiektów używanych w programie. We wcześniejszych wersjach Pythona (do wersji 1.6) interpreter Pythona wykorzystywał jedynie mechanizm zliczania referencji do obsługi pamięci. Gdy liczba referencji spadnie do zera, interpreter Pythona automatycznie zwalnia pamięć. Ten klasyczny mechanizm liczenia referencji jest bardzo skuteczny, z wyjątkiem tego, że nie działa, gdy w programie występują cykle referencyjne. Cykl referencyjny występuje wtedy, gdy jeden lub więcej obiektów odwołuje się do siebie nawzajem, a zatem liczba referencji nigdy nie osiąga zera.

Rozważmy przykład.

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

Powyższy kod tworzy cykl referencyjny, w którym obiekt list odwołuje się do samego siebie. W związku z tym pamięć obiektu list nie zostanie automatycznie zwolniona po powrocie funkcji. Problem cyklu referencyjnego nie może być rozwiązany przez liczenie referencji. Jednak ten problem cyklu referencyjnego można rozwiązać, zmieniając zachowanie garbage collectora w aplikacji Pythona.

Aby to zrobić, możemy użyć funkcji gc.collect() z modułu gc.

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

Funkcja gc.collect() zwraca liczbę obiektów, które zebrała i odmiejscowiła.

Istnieją dwa sposoby wykonywania ręcznego zbierania śmieci: zbieranie śmieci oparte na czasie lub zbieranie śmieci oparte na zdarzeniach.

Zbieranie śmieci oparte na czasie jest dość proste: funkcja gc.collect() jest wywoływana po ustalonym interwale czasowym.

Odśmiecanie oparte na zdarzeniach wywołuje funkcję gc.collect() po wystąpieniu zdarzenia (tj. gdy aplikacja jest zamykana lub pozostaje bezczynna przez określony czas).

Zrozummy ręczną pracę odśmiecania, tworząc kilka cykli referencyjnych.

Wyjście jest takie jak poniżej:

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

Powyższy skrypt tworzy obiekt listy, do którego odwołuje się zmienna o twórczej nazwie list. Pierwszy element obiektu listy odnosi się do samego siebie. Liczba referencji obiektu listy jest zawsze większa od zera, nawet jeśli jest on usunięty lub znajduje się poza zakresem programu. Dlatego też obiekt list nie jest odśmiecany z powodu odwołania kołowego. Mechanizm garbage collector w Pythonie będzie automatycznie sprawdzał i okresowo zbierał odwołania kołowe.

W powyższym kodzie, ponieważ liczba odwołań wynosi co najmniej 1 i nigdy nie może osiągnąć 0, wymusiliśmy odśmiecanie obiektów przez wywołanie gc.collect(). Należy jednak pamiętać, aby nie wymuszać odśmiecania często. Powodem jest to, że nawet po zwolnieniu pamięci, GC potrzebuje czasu, aby ocenić, czy obiekt kwalifikuje się do odśmiecania, co zabiera czas i zasoby procesora. Pamiętaj również, aby ręcznie zarządzać garbage collectorem dopiero po całkowitym uruchomieniu aplikacji.

Podsumowanie

W tym artykule omówiliśmy, w jaki sposób zarządzanie pamięcią w Pythonie jest obsługiwane automatycznie za pomocą strategii liczenia referencji i garbage collection. Bez garbage collection wdrożenie skutecznego mechanizmu zarządzania pamięcią w Pythonie jest niemożliwe. Programiści nie muszą się również martwić o usuwanie zaalokowanej pamięci, ponieważ zajmuje się tym menedżer pamięci Pythona. Prowadzi to do mniejszej liczby wycieków pamięci i lepszej wydajności.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.