2013-03-29 6 views
10

Mam problem ze zbieraniem śmieci w Rubim, gdzie obiekt, który moim zdaniem powinien być zbiorem śmieci, nie jest zbiorem śmieci.Kolekcja Garbarge w Ruby z obiektami okrągłymi Referencje

require 'ruby-mass' 

def find_dependencies(_object_id,_mapped = {}) 
    mapped = _mapped 
    points_to_object = Mass.references(Mass[_object_id]) 
    ids = points_to_object.keys.map{|x| /\#(\d*)/.match(x).captures.first.to_i} 
    mapped[_object_id] = ids 

    unmapped = ids - mapped.keys 
    unmapped.each do |x| 
    new_deps = find_dependencies(x,mapped) 
    mapped.merge(new_deps) 
    end 
    mapped 
end 

Zrób coś, co tworzy obiekty i znajdź odpowiedni identyfikator obiektu. GC.start, a następnie:

> find_dependencies(144789180) 
=> {144789180=>[61895480, 144786340, 147807540], 
61895480=>[144789180], 
144786340=>[144789180], 
147807540=>[144789180]} 

Wygląda na to, że jest okrągły wzorca odniesienia, ale to wszystko jest całkowicie zawarty w tych czterech obiektów, więc kolektor Mark-and-Sweep powinien je znaleźć i usunąć je.

Tak, albo jest błąd w moim find_dependencies_function, Mass gem, albo śmieciowym zbieraczu Rubiego. Jak zawęzić to, aby dowiedzieć się, na czym polega problem i rozwiązać ten problem z wyciekiem pamięci?

+3

Mark-and-zamiatać nie może obsłużyć tego rodzaju rzeczy. Aby to zrobić, musisz użyć WeakRef w tych obiektach, aby umożliwić kolektorowi usunięcie całego drzewa. – Linuxios

+0

Dlaczego nie można oznaczać i omiatać obsługiwać te rzeczy? Widzę, jak prześlizgnęliby się przez liczenie odwołań, ale te nie powinny być zaznaczone i powinny zostać zebrane, nie? – aaronjg

+0

Najpierw muszę zapytać - jak tracisz odniesienie do obiektu? Czy są absolutnie * nie * inne odniesienia do podobiektów? – Linuxios

Odpowiedz

2

GC Ruby pracuje w zasadzie tak:

  1. Oznacz wszystkie obiekty globalne jak na żywo.

  2. Przeszukuj obiekty, odśmiecaj śmieci, chyba że rodzic jest aktywny.

Tak więc, w przypadku odwołania cyklicznego, trzymanie na B, które trzyma A, otrzymałoby GC, ponieważ żaden nie jest trzymany przez żywy obiekt.

Per komentarzach, coś niekoniecznie trzymając obiektu gdzieś ... A może Mass łapie RangeError czy coś ...

>> a = {} 
=> {} 
>> a[:a] = a 
=> {:a=>{...}} 
>> a.object_id 
=> 2269556540 
>> a = nil 
=> nil 
>> GC.start 
=> nil 
>> ObjectSpace._id2ref(2269556540) 
RangeError: 0x8746af3c is recycled object 
    from (irb):17:in `_id2ref' 
    from (irb):17