/ We know how

Czym jest garbage collector i jak działa?

Świat programowania idzie naprzód, czego najważniejszym dowodem jest automatyzacja i szereg czynności, które nie leżą już w obowiązku osoby zajmującej się wytwarzaniem i rozwijaniem kodu programistycznego. Jednym z najważniejszych i najbardziej przydatnych narzędzi, które służą programiście w zwiększeniu efektywności jego pracy, jest Garbage Collector. Czym jest i jak działa Garbage Collector w różnych językach programowania?

 

 

Czym jest garbage collector (GC)?

 

Programowanie w czystej postaci bardzo często ogranicza się do tworzenia funkcjonalności, które jak dobrze wiadomo, zajmują pamięć naszego komputera. Choć jest ona niezwykle obszerna, to nie możemy w nieskończoność zajmować i nadpisywać dynamicznie alokowanej pamięci. W dawnych latach, gdzie języki nieobiektowe, takie jak C czy C++ stanowiły najważniejszą technologię służącą rozwijaniu oprogramowania, programista samodzielnie był odpowiedzialny za to, by ręcznie zwalniać pamięć zablokowaną przez niewykorzystywane, stare obiekty, które do niczego nam się już nie przydadzą.

Dlatego też technologia opracowana ponad 70 lat temu, na potrzeby języka LISP dopiero po wielu latach zyskała prawdziwe uznanie i stanowi jeden z najczęściej wykorzystywanych mechanizmów przy programowaniu w językach takich, jak Java, Ruby, Python czy C#. Mowa tu o Garbage Collector – technologii, która odpowiedzialna jest za automatyczne zwalnianie pamięci poprzez regularną weryfikację stanu pamięci i usuwanie tych obiektów, które uznane są za niepotrzebne. Choć mechanika działania Garbage Collector jest niezwykle prosta, to stanowi ono ogromne wsparcie w utrzymaniu optymalnej efektywności programistów i jest do dziś stosowane podczas pracy z najważniejszymi technologiami.

 

 

Dlaczego GC jest potrzebny?

 

Z czego wynika tak istotna waga małego narzędzia, jakim jest Garbage Collector? Z całą pewnością nowi programiści, którzy nie poznali dostatecznie „zaprzeszłych” technologii, którymi jeszcze kilkanaście lat temu posługiwali się starsi koledzy deweloperzy, nie doceniają wagi tego mechanizmu.

Ci jednak, którzy programowali w C czy C++ z pewnością doskonale pamiętają komendy free bądź delete, które służyły usuwaniu zbędnych referencji do obiektów. I choć nawet w małych aplikacjach proces usuwania „śmieci” nie był tak istotny, to jednak rozbudowa dużej, funkcjonalnej aplikacji wymaga regularnego czyszczenia kodu, który bardzo często zwracał nam błąd informujący o niedostatecznej pamięci.

Nieodpowiednie zarządzanie pamięcią w przeszłości, jak i obecnie może w dużej mierze wpłynąć na optymalną szybkość działania aplikacji, jej stabilność a w skrajnych przypadkach nawet na jej bezpieczeństwo. Źle zarządzana pod kątem pamięciowym aplikacja to łakomy kąsek dla rosnących w popularność ataków DoS.

 

 

Jak działa garbage collector?

 

Przeanalizujmy, jak dokładnie działa Garbage Collector. Nowoczesne algorytmy, które służą identyfikowaniu i czyszczeniu kodu ze zbędnych obiektów, działają w dwóch podstawowych typach:

  • skalarnym
  • wektorowym

Wariant algorytmu skalarnego działa na zasadzie zliczania referencji do konkretnego obiektu. Mechanizm inkrementuje i dekrementuje w przypadku dodania lub usunięcia konkretnej referencji. Jeśli okazuje się, że na przestrzeni całego kodu wartość zliczania jest równa zeru, obiekt jest usuwany, a pamięć dotychczas zajmowana przez dany obiekt i referencje jest zwalniana. Wydawałoby się, że algorytm skalarny to idealne rozwiązanie, które w swojej prostocie załatwia cały problem czyszczenia pamięci. Niestety ma on jedną, bardzo istotną wadę. Algorytm skalarny nie identyfikuje cyklicznych referencji. W obliczu tego zagrożenia zaprojektowano alternatywę, której cechą charakterystyczną jest identyfikowanie obiektów nie jako płaskie struktury, a grafy. Chodzi o algorytm wektorowy.

Algorytmy wektorowe, znane też pod nazwą algorytmów śledzących umieszczają wszystkie obecne w kodzie obiekty w grafie, po czym przechodząc przez niego, oznaczają te, które mechanizm odnalazł w postaci referencji. Wszystkie obiekty, które nie mają referencji, są automatycznie usuwane przez technologię Garbage Collector. W praktyce proces ten dzieje się w tle i programista nawet nie musi być świadomy, że czyszczenie pamięci odbywa się regularnie.

 

 

Garbage Collector – różnice w językach

 

Garbage Collector jest obecny we wszystkich powszechnie stosowanych obiektowych językach programowania. Co istotne, implementacja tego mechanizmu różni się ze względu na technologię. Podstawowa różnica wynika z wdrożenia takiego rozwiązania w swoim kodzie. Zdecydowana większość języków wysokiego poziomu posiada Garbage Collector jako funkcję wbudowaną automatycznie w środowisko programistyczne. Doskonałym przykładem będzie wcześniej wspomniana Java czy C#. Wciąż jednak w świecie programistycznym obecne są języki (szczególnie te niskiego poziomu) wykorzystujące technologię zwalniania pamięci poprzez wykorzystanie dodatkowych bibliotek.

Różnice w implementacji i sposobie wykorzystana GC (wariant skalarny i wektorowy) wynikają także z prostej przyczyny, jaką jest zastosowanie danego języka. Jak dobrze wiadomo, każdy język programowania służy innym celom, dlatego też odpowiednie wdrożenie technologii Garbage Collector w sposób odmienny w każdym języku było istotne, by zachować integralność kodu, sposobu kompilacji oraz optymalnego wykorzystania technologii w powszechnym zastosowaniu.