2013-06-03 10 views
31

Zauważyłem, że pamięć przeglądarki zaczyna się zwiększać, gdy jestem w formie (jest to zauważalne przez menedżera zadań). W IE 9, po pewnym użyciu idzie to łatwo ponad 500 MB, podczas gdy chrom jest bardziej odporny (idzie do 200 MB przy użyciu tego samego testu).Wycieki pamięci Javascript: drzewo DOM jednoosobowe

Używam narzędzi programistycznych Chrome do debugowania tego problemu. Zauważyłem, że istnieje duża liczba wolnostojący DOM drzewa:

detached dom tree screenshot

jestem zakładając, że może to potwierdzić, że jest wyciek pamięci. Czy to prawda? Po drugie, musiałbym dowiedzieć się, jak zidentyfikować główną przyczynę problemu. Wiem, że powinieneś użyć drzewa przytrzymującego, aby określić, co powstrzymuje te elementy przed odzyskaniem. Ale nie mogę się dowiedzieć, jak użyć drzewa przytrzymującego. Na przykład, co oznacza drzewo podtrzymujące na powyższym zrzucie ekranu?

Każda pomoc będzie mile widziana.

+2

Czy możesz wyjaśnić, że "pamięć przeglądarki zaczyna się zwiększać, gdy jestem w formie" z pewnym kodem? To pomaga znaleźć wyciek pamięci. – Ikrom

+0

Czy [to inne pytanie/odpowiedź] (http://stackoverflow.com/questions/11930050/finding-js-memory-leak-in-chrome-dev-tools) pomaga? – msung

Odpowiedz

25

Podczas pisania kodu odwołującego się do elementów DOM należy pamiętać o wielu kwestiach. Ale zasadniczo wszystko sprowadza się do kilku prostych punktów -

a. W ramach funkcji lokalnych należy zawsze wyczyścić odniesienie Nigdy nie przechowuj odniesień jako części danych elementu .data()

c. Staraj się nie używać odwołań DOM wewnątrz ładowarki zamknięcia/inline, zamiast przechodzić identyfikatory

function attachClick(){ 
     var someDiv = $('#someDiv'); 

     someDiv.click(function(){ 
     var a = someDiv....; 
     //Wrong. Instead of doing this.. 
     }); 


     someDiv.click(function(){ 
     var a = $('#someDiv'); 
     //Pass the identifier/selector and then use it to find the element 
     });  


     var myFunc = function(){ 
     var a = someDiv; 
     //using a variable from outside scope here - big DON'T!    
     } 
    } 

Tak, można argumentować, że poszukiwania elementów może zwolnić stronę w dół, ale opóźnienie jest bardzo minimalne w porównaniu z wykonywaniem hit ogromna sterty przyczyny esp. w dużych pojedynczych aplikacjach. Dlatego też # 3 powinno być używane tylko po zważeniu zalet i wad. (To pomogło znacząco w moim przypadku)

UPDATE

d. Unikaj anonimowych funkcji - nazywanie procedur obsługi zdarzeń i lokalnych funkcji bardzo ci pomoże podczas profilowania/przeglądania migawek sterty.

+0

Musiałbym się nie zgodzić z (c), jedyny czas, który spowodowałby, że problem byłby imo, gdyby kolejne wywołanie funkcji zwróciło zamknięcie lub wykonało operację, która zachowała odniesienie do przekazanego elementu dom (lub jQuery owiniętego element) - tjjak przechowywanie elementu na liście statycznej lub tworzenie pewnego rodzaju odwołania cyklicznego. Czy masz przykład, gdzie zwykłe przekazanie elementu do metody spowodowałoby problem? – Pebbl

+2

@pebbl: Sprawdziłem z moim kodem. Masz rację. Miałem na myśli zamykanie, a nie tylko przekazywanie ich metodom. Poprawiony przykład powyżej. –

+0

Ah, miło. Dziękuję za wyjaśnienia, teraz o wiele jaśniejsze. – Pebbl

2

Wygląda na to, że twój kod tworzy wiele poddrzewa DOM i utrzymuje odniesienia do niego z javascript. Musisz wybrać element z drzewa wolnostojącego. Zgodnie z migawką powinieneś wybrać element Tekst. I spójrz na drzewo opiekunów.

To drzewo pokazuje wszystkie ścieżki, które utrzymują obiekt przy życiu. Przynajmniej jedna ścieżka, zwykle najkrótsza, doprowadzi cię do obiektu okna. Jeśli znasz kod, możesz łatwo znaleźć obiekt w tej ścieżce, który musi zostać usunięty, ale tak nie jest. Na ścieżce może znajdować się wiele takich obiektów. Obiekt o najmniejszej odległości jest bardziej interesujący.