Znajdowanie wycieków pamięci JavaScript w Chrome
Stworzyłem bardzo prosty przypadek testowy, który tworzy widok szkieletowy, dołącza obsługę do zdarzenia i tworzy instancje klasy zdefiniowanej przez użytkownika. Wierzę, że klikając przycisk "Usuń" w tej próbce, wszystko zostanie wyczyszczone i nie powinno być wycieków pamięci.
Jsfiddle dla kodu jest tutaj: http://jsfiddle.net/4QhR2/
// scope everything to a function
function main() {
function MyWrapper() {
this.element = null;
}
MyWrapper.prototype.set = function(elem) {
this.element = elem;
}
MyWrapper.prototype.get = function() {
return this.element;
}
var MyView = Backbone.View.extend({
tagName : "div",
id : "view",
events : {
"click #button" : "onButton",
},
initialize : function(options) {
// done for demo purposes only, should be using templates
this.html_text = "<input type='text' id='textbox' /><button id='button'>Remove</button>";
this.listenTo(this,"all",function(){console.log("Event: "+arguments[0]);});
},
render : function() {
this.$el.html(this.html_text);
this.wrapper = new MyWrapper();
this.wrapper.set(this.$("#textbox"));
this.wrapper.get().val("placeholder");
return this;
},
onButton : function() {
// assume this gets .remove() called on subviews (if they existed)
this.trigger("cleanup");
this.remove();
}
});
var view = new MyView();
$("#content").append(view.render().el);
}
main();
Nie jestem jednak pewien, jak użyć profilera Google Chrome, aby zweryfikować, że tak jest w rzeczywistości. Jest gazillion rzeczy, które pojawiają się na migawce profilera sterty i nie mam pojęcia, jak rozkodować to, co dobre/złe. Samouczki, które widziałem na nim do tej pory, albo po prostu mówią mi, żebym "używał profilera migawkowego", albo dają mi bardzo szczegółowy Manifest na temat tego, jak działa cały profiler. Czy można po prostu użyć profilera jako narzędzia, czy naprawdę muszę zrozumieć, w jaki sposób całość została zaprojektowana?
EDIT: tutoriale takie jak te:
Wyciek pamięci Gmail mocowanie
Reprezentują niektóre z mocniejszych materiałów tam, z tego, co widziałem. Jednak poza wprowadzeniem koncepcji 3 migawki techniki , uważam, że oferują one bardzo niewiele pod względem praktycznej wiedzy (dla początkującego jak ja). Samouczek "Korzystanie z DevTools" nie działa na prawdziwym przykładzie, więc jego niejasny i ogólny koncepcyjny opis rzeczy nie jest zbyt pomocny. Co do "Gmaila" przykład:
Jestem bardziej zdezorientowany po przeczytaniu tego, nie mniej. I znowu, to tylko mówi mi, że mam robić rzeczy, a nie jak to robić. Z mojego punktu widzenia wszystkie informacje są albo zbyt niejasne, albo mają sens tylko dla kogoś, kto już zrozumiał proces.więc znalazłeś przeciek. Co teraz?
Zbadaj ścieżkę zatrzymywania wycieków obiektów w dolnej połowie panelu Profile
Jeśli miejsce alokacji nie może być łatwo wywnioskowane (np. słuchacze zdarzeń):
Przyrząd konstruktora obiektu zatrzymującego za pomocą konsoli JS, aby zapisać ślad stosu dla alokacji
Używając Zamknięcia? Włącz odpowiednie istniejące flaga (tj. goog.wydarzenia.Słuchacz.ENABLE_MONITORING), aby ustawić właściwość creationStack podczas budowy
Niektóre z tych bardziej szczegółowych kwestii zostały poruszone w @Jonathan Naguin ' s answer poniżej.
7 answers
Dobrym przepływem pracy, aby znaleźć wycieki pamięci, jest technika trzy migawki , po raz pierwszy wykorzystana przez Loreenę Lee i zespół Gmail do rozwiązania niektórych problemów z pamięcią. Kroki są, ogólnie:
- Zrób zdjęcie sterty. Rób różne rzeczy.
- zrób kolejne zdjęcie sterty. Powtórz to samo.
- zrób kolejne zdjęcie sterty.
- filtruje obiekty przydzielone pomiędzy migawkami 1 i 2 w widoku "podsumowanie" migawki 3.
Dla Twojego przykładu, ja dostosowano kod, aby pokazać ten proces (można go znaleźć tutaj) opóźniając Tworzenie widoku szkieletowego do momentu kliknięcia przycisku Start. Teraz:
- Uruchom HTML (zapisany lokalnie z tego adresu ) i Zrób migawkę.
- Kliknij przycisk Start, aby utworzyć widok. Zrób kolejne zdjęcie.
- kliknij Usuń. Zrób kolejne zdjęcie.
- Filtruj obiekty przydzielone między migawkami 1 i 2 w "podsumowaniu migawki 3" widok.
Teraz jesteś gotowy, aby znaleźć wycieki pamięci!
Zauważysz węzły o kilku różnych kolorach. Czerwone węzły nie mają bezpośrednich odniesień z Javascript do nich, ale są żywe, ponieważ są częścią oddzielonego drzewa DOM. W drzewie może znajdować się węzeł odwołujący się do Javascript (może jako zamknięcie lub zmienna), ale przypadkowo uniemożliwia zbieranie śmieci przez całe drzewo DOM.
Żółte węzły mają jednak bezpośrednie odwołania z Javascript. Poszukaj żółtych węzłów w tym samym oddzielonym drzewie DOM, aby zlokalizować odwołania z twojego Javascript. Powinien istnieć łańcuch właściwości prowadzący z okna DOM do elementu.
W twoim konkretnym możesz zobaczyć element HTML div oznaczony jako czerwony. Jeśli rozwiń element, zobaczysz, że jest odwołany przez funkcję "cache".
Wybierz wiersz i w konsoli wpisz $0, zobaczysz rzeczywistą funkcję i lokalizacja:
>$0
function cache( key, value ) {
// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
if ( keys.push( key += " " ) > Expr.cacheLength ) {
// Only keep the most recent entries
delete cache[ keys.shift() ];
}
return (cache[ key ] = value);
} jquery-2.0.2.js:1166
To jest miejsce, gdzie twój element jest odwołany. Niestety niewiele można zrobić, jest to wewnętrzny mechanizm z jQuery. Ale, dla celów testowych, przejdź do funkcji i zmień metodę na:
function cache( key, value ) {
return value;
}
Teraz, jeśli powtórzysz proces, nie zobaczysz żadnego czerwonego węzła :)
Dokumentacja:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-01 12:37:21
Oto wskazówka na temat profilowania pamięci jsfiddle: Użyj następującego adresu URL, aby wyizolować wynik jsfiddle, usuwa on wszystkie ramy jsfiddle i ładuje tylko wynik.
Http://jsfiddle.net/4QhR2/show/
Nigdy nie byłem w stanie dowiedzieć się, jak używać osi czasu i profilera do śledzenia wycieków pamięci, dopóki nie przeczytałem poniższej dokumentacji. Po przeczytaniu sekcji "Object allocation tracker" mogłem skorzystać z narzędzia "Record Heap Allocations" , i wyśledzić kilka odłączonych węzłów DOM.
Naprawiłem problem poprzez przejście z wiązania zdarzeń jQuery na delegowanie zdarzeń szkieletowych. Rozumiem, że nowsze wersje Backbone automatycznie odpiszą zdarzenia, jeśli wywołasz View.remove()
. Wykonaj niektóre dema samodzielnie, są one skonfigurowane z wyciekami pamięci, które możesz zidentyfikować. Nie krępuj się zadawać pytań tutaj, jeśli nadal nie rozumiesz tego po przestudiowaniu tego dokumentacja.
Https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-01 13:55:08
Zasadniczo musisz spojrzeć na liczbę obiektów wewnątrz Twojej migawki sterty. Jeśli liczba obiektów zwiększy się między dwoma migawkami, a obiekty zostaną usunięte, wystąpi wyciek pamięci. Moja rada polega na tym, aby w Twoim kodzie znaleźć procedury obsługi zdarzeń, które nie zostaną odłączone.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-27 17:33:30
Możesz też przeczytać:
Http://addyosmani.com/blog/taming-the-unicorn-easing-javascript-memory-profiling-in-devtools/
Wyjaśnia korzystanie z narzędzi programistycznych chrome i daje kilka wskazówek krok po kroku, jak potwierdzić i zlokalizować wyciek pamięci za pomocą porównania migawek sterty i różnych dostępnych widoków migawek hep.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-15 09:56:43
Jest film wprowadzający od Google, który będzie bardzo pomocny w znalezieniu wycieków pamięci JavaScript.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-14 07:59:59
Możesz również spojrzeć na zakładkę oś czasu w narzędziach programistycznych. Rejestruj korzystanie z aplikacji i miej oko na węzeł DOM i liczbę detektorów zdarzeń.
Jeśli Wykres pamięci rzeczywiście wskazuje wyciek pamięci, możesz użyć profilera, aby dowiedzieć się, co wycieka.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-30 08:35:52
[1]}popieram radę, aby zrobić migawkę sterty, są doskonałe do wykrywania wycieków pamięci, chrome robi świetną robotę snapshotting.
W moim projekcie badawczym dla mojego stopnia budowałem interaktywną aplikację internetową, która musiała generować wiele danych wbudowanych w "warstwy", wiele z tych warstw zostanie "usuniętych" w interfejsie użytkownika, ale z jakiegoś powodu pamięć nie była dealokowana, za pomocą narzędzia migawki byłem w stanie ustalić, że JQuery trzymał odniesienie na stronie. obiekt (źródło było wtedy, gdy próbowałem wywołać zdarzenie .load()
, które utrzymywało odniesienie pomimo wyjścia poza zakres). Mając te informacje pod ręką samodzielnie zapisałem mój projekt, jest to bardzo przydatne narzędzie, gdy korzystasz z bibliotek innych ludzi i masz ten problem z utrzymywaniem odniesień powstrzymujących GC od wykonywania swojej pracy.
Edytuj: Warto również zaplanować z wyprzedzeniem, jakie działania zamierzasz wykonać, aby zminimalizować czas spędzony na robieniu zdjęć, hipotezować, co może być przyczyną problem i przetestuj każdy scenariusz, tworząc migawki przed i po.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-06 09:26:41