W skrócie : śmieciarze nie używają rekurencji. Kontrolują tylko śledzenie, śledząc zasadniczo dwa zestawy (które mogą się łączyć). Kolejność śledzenia i przetwarzania komórek jest nieistotna, co daje znaczną swobodę implementacji do reprezentowania zbiorów. Dlatego istnieje wiele rozwiązań, które w rzeczywistości są bardzo tanie w użyciu pamięci. Jest to niezbędne, ponieważ GC jest wywoływana właśnie wtedy, gdy na stosie zabraknie pamięci. W przypadku dużych wirtualnych pamięci sytuacja wygląda nieco inaczej, ponieważ nowe strony można łatwo przydzielić, a wrogowi nie jest brak miejsca, ale brak lokalizacji danych
.
Zakładam, że rozważasz śledzenie śmieciarek, a nie liczenie referencji, do których twoje pytanie nie wydaje się mieć zastosowania.
UV
Pierwszą rzeczą, na którą należy zwrócić uwagę, jest to, że wszystkie śledzące GC są oparte na tym samym abstrakcyjnym modelu, opartym na systematycznym badaniu ukierunkowanego wykresu komórek w pamięci dostępnej z programu, gdzie komórki pamięci są wierzchołkami, a wskaźniki są skierowanymi krawędziami. Wykorzystuje do tego następujące zestawy:
VUUT
UV
UcVUcUT
UUV=TVH−VV
VUUT
Pomijam też szczegóły na temat tego, co to jest komórka, czy są one w jednym rozmiarze, czy w wielu, w jaki sposób znajdujemy w nich wskaźniki, jak można je zagęścić, a także wiele innych problemów technicznych, które można znaleźć w książkach i ankietach na temat usuwania śmieci .
U
Różnice między znanymi implementacjami dotyczą sposobu, w jaki te zestawy są faktycznie reprezentowane. Zastosowano wiele technik:
mapa bitowa: Część mapy pamięci jest zachowana dla mapy, która ma jeden bit dla każdej komórki pamięci, którą można znaleźć za pomocą adresu komórki. Bit jest włączony, gdy odpowiednia komórka znajduje się w zestawie zdefiniowanym przez mapę. Jeśli używane są tylko mapy bitowe, potrzebujesz tylko 2 bity na komórkę.
alternatywnie możesz mieć miejsce na specjalny bit znacznika (lub 2) w każdej komórce, aby go oznaczyć.
log2pp
możesz przetestować orzeczenie dotyczące zawartości komórki i jej wskaźników.
możesz przenieść komórkę do wolnej części pamięci przeznaczonej dla wszystkich komórek należących do reprezentowanego zestawu.
VTTU
możesz połączyć te techniki, nawet dla jednego zestawu.
Jak już powiedziano, wszystkie powyższe zostały wykorzystane przez jakiś zaimplementowany moduł wyrzucania elementów bezużytecznych, co może wydawać się dziwne. Wszystko zależy od różnych ograniczeń wdrożenia. I mogą być dość tanie w użyciu pamięci, być może pomocne w przetwarzaniu zasad zamówień, które mogą być dowolnie wybrane do tego celu, ponieważ nie mają znaczenia dla wyniku końcowego.
To, co może wydawać się najdziwniejsze, przenoszenie komórek w nowym obszarze, jest w rzeczywistości bardzo powszechne: nazywa się to zbieraniem kopii. Najczęściej jest używany z pamięcią wirtualną.
Oczywiście nie ma rekurencji, a stos algorytmu mutatora nie musi być używany.
Inną ważną kwestią jest to, że wiele nowoczesnych GC jest implementowanych dla dużych wirtualnych pamięci . Pozyskanie miejsca do wdrożenia i dodatkowej listy lub stosu nie stanowi problemu, ponieważ nowe strony można łatwo przypisać. Jednak w dużych wirtualnych wspomnieniach wrogiem nie jest brak miejsca, ale brak lokalizacji . Następnie struktura reprezentująca zestawy i ich użycie muszą być ukierunkowane na zachowanie lokalizacji struktury danych i wykonywania GC. Problemem nie jest przestrzeń, ale czas. Niewłaściwe implementacje częściej wykazują niedopuszczalne spowolnienie niż przepełnienie pamięci.
Nie podałem odniesień do wielu konkretnych algorytmów wynikających z różnych kombinacji tych technik, ponieważ wydaje się to wystarczająco długie.