32

Mam pytanie dotyczące zbierania śmieci w Google Chrome (wersja 20.0.1132.47, Ubuntu 11.04, 64-bitowy).Instancje, do których odnosi się tylko "bound_this", nie są odpadami śmieci.

Podczas porównywania stert-zrzutów i sprawdzania wycieków pamięci, odkryłem kilka przypadków, które nigdy nie zostały oczyszczone. Normalnie takie zachowanie może być śledzone w dół do programatora-błędem, ale w tym przypadku jestem raczej pojęcia ..

Spójrz na poniższy zrzut ekranu Screenshot of heap-dump showing an instance (child) referenced only by 'bound_this'

Instancja „dziecko @ 610739” odwołuje tylko przez instancje "bound_this", które należą do funkcji samej instancji potomnej. Tak więc, jak rozumiem, instancja potomna powinna być zbiorem śmieci, ponieważ jedyną inną referencją trzymającą ją jest sama instancja potomna (poprzez funkcje "bound_this").

używam funkcji underscore.js' 'bindAll' użytkową (underscore.js#bindAll), który mapuje do 'native_bind' funkcji chromu (ECMA Script wiki on bound_this)

Am I brakuje czegoś tutaj oczywiste i jeśli tak, to może ktoś wytłumaczyć co utrzymuje te instancje przy życiu?

UPDATE:
W międzyczasie testowałem samej aplikacji w chrominium (18.0.1025.168 (Twórca Budowanie 134367 Linux) Ubuntu 11.10), które nie wykazują te zwisające instancji ..

UPDATE 2:
obserwuję Esailijas wskazówka, aby zapewnić jsfiddle snippet, stworzyłem jeden (http://jsfiddle.net/8gSTR/1/), który naśladuje to, co zasadniczo robię. Uruchomienie tego skrzypiec niestety nie pokazuje niewłaściwego zachowania, którego doświadczam w mojej aplikacji. Sterty-dump podjęte podczas „A'-instancje są nadal odwoływać wygląda niby podobna, choć mimo odniesienia z tablicy window.o który utrzymuje instancje żywe: Heap-dump taken during execution of jsfiddle mentioned above

jako takie odniesienie brakuje w moim przypadku (zrzut ekranu 1) Nie wiem, co powstrzymuje Chrome przed uwolnieniem tych instancji ...

AKTUALIZACJA 3:
Po wykonaniu porady Loislosa, aby włączyć ukryte właściwości. Wynik (z jedną z rozwiniętych gałęzi) można zobaczyć na poniższym zrzucie ekranu, ale nie zajmuje mi to więcej. Heap-dump with hidden properties enabled

+0

Nie widzisz tego tutaj http://jsfiddle.net/uGX22/3/. Początkowo są tam (Heap zabiera 17.32mb z 60000 zamknięciami), czekam kilka minut i zrobię nową migawkę, a stertę z powrotem do 6mb i zamknięcia nie ma. Czy możesz zmodyfikować moje jsfiddle, aby to odtworzyć? – Esailija

+0

Czy możesz pokazać nam kod, z którym stworzyłeś tę sytuację? Naprawdę nie dostaję tego ze zrzutu debuggera. – Bergi

+0

Postaram się utworzyć mały fragment do odtworzenia problemu. Kod, z którym stworzyłem tę sytuację, jest częścią dość dużego SPA, więc nie jest to łatwe do wyodrębnienia. –

Odpowiedz

3

Twoje podejrzenia, że ​​to nie jest faktyczny wyciek pamięci, ale dziwność z chromem jest prawidłowa.

Niedawno natknąłem się na ten sam problem. IE11 nie pokaże this.func = _.bind (this.func, this) jako wycieku pamięci, podczas gdy chrome będzie, nawet po naciśnięciu przycisku zbierania śmieci 100 razy.

Pokaże to nawet po uruchomieniu chrome z bzdurami jsflag i odsłonięciu leżącego niżej garbage collector i wywołaniu 100 razy gc.

Łatwym sposobem udowodnienia, że ​​w rzeczywistości nie jest to wyciek w chrome, jest niewielkie obciążenie poważnym problemem w przeglądarce i zmuszenie silnika do działania.

Na przykład, który ma funkcję związaną przypisany do niego przypisać nową właściwość takiego:

target.WhyAmILeaking = new Array (200000000) .join ("YOURNOT");

Wykonaj trzy techniki snapshot za pomocą chrome, a zobaczysz, że ten ciąg obecny jest w taktowaniu sterty na około 214mb. Wykonaj ponownie dowolną konstruktywną akcję (druga migawka), a zobaczysz, że sterta przechodzi do 423 MB lub pozostanie przy 214 MB. Jeśli zostanie, skończysz, gdy udowodniłeś, że zostało zebrane oryginalne 214 MB. Jeśli nie pozostanie, wykonaj niszczycielską akcję (trzecia migawka) i wróci do 214mb, co również udowodni, że oryginał został zebrany.

Jeśli po prostu pozostanie na 423mb, Pan lub Pani ma wyciek.

No i kolejna grupa biednych dusz, które biegł dokładnie tej samej sytuacji: https://github.com/jashkenas/backbone/issues/2269#issuecomment-13610969

TL; DR; użyj IE 11 do wykrywania wycieków.

1

I, o których mowa w tym w EcmaScript, termin „związany to” z klasy

Metody klasy są „związany ten”, w przypadku gdy w organizmie metoda jest zawsze związany z przykładu klasy, z których metoda została wyodrębniona, niezależnie od tego, jaki parametr jest faktycznie przekazywany do metody (ten parametr metody jest ignorowany).

Teraz tutaj w przykładzie nie ma skrypt podane więc nie mogą być specyficzne pytanie

muszę powiedzieć, jeśli nie jest to wyciek ..

następnie co kiedykolwiek sprzeciw, Klasa Skrypt jest ograniczony, nie wywoła śmieci, dopóki klasa/obiekt nie istnieje, ponieważ ta funkcja jest ograniczona tym samym obiektem. To śmieci będzie zbierane tylko po zakończeniu jego obiektu macierzystego (obiektu/klasy, z którym jest ograniczony).

Teraz, jeśli cykliczne odwołanie, gdy zadanie się zakończy, to się skończy, >> to działa jak koncepcja rekursji (pamiętaj, że koncepcja, nie to samo co ...), więc koniec rozpocznie się od ostatniego połączenia .. w odwrotne ... wewnętrzne wywołanie (ostatnie wywołanie) zostanie zwolnione po raz pierwszy i tak dalej.

Kod musi być błędny, ponieważ nie może wiązać się i definiować funkcji i używać ich ponownie za każdym razem .. ale jeśli są one wiążące to również powinien działać poprawnie i nie powinien przeciekać, dopóki ślad nie zniknie z limitu przeglądarki na pulę pamięci.

Mam nadzieję, że będzie to wyjaśnić ..

1

Czy wyzwolenie „zmuszone GC” za pomocą narzędzi programistycznych? Jeśli tak jest, a obiekty następnie się utrzymują, powyższe badania mają wartość.

Jeśli nie uruchamiasz GC za pomocą narzędzi programistycznych, to pamiętaj, że sposób działania silnika GC jest dość skomplikowany i ma koncepcję generowania kolekcji (przy użyciu dwóch generacji).

http://www.html5rocks.com/en/tutorials/memory/effectivemanagement/#toc-v8-gc

To może być po prostu, że nie osiągnęły wymaganego progu do wyzwalania młodą GC generacji, albo, że obiekty zostały zwyczajnych do starego pokolenia, ale że stare pokolenie GC nigdy nie został uruchomiony.

Niestety, narzędzia programistyczne nie wydają się pokazywać, które generowanie było generowane przez GC.