Problemy z pamięcią Javascript i wyciekiem

Moja strona jest dość standardową witryną ecom, nie jest to samodzielna aplikacja wspierana przez JS ani nic, to po prostu strona, która używa JS do standardowych rzeczy, a także niektórych wtyczek jquery do zrobienia kilku rzeczy.

Próbuję dokonać oceny pamięci JS na mojej stronie. Zrobiłem to, patrząc na Menedżera zadań Chrome i za pomocą migawek sterty.

Initailly Moja Strona przy pierwszym załadowaniu znajduje się między 35MB (tj. Jest to największa z każdej karty, jeśli mam kilka zakładek innych stron internetowych otwiera się w tym samym czasie. Jak odświeżę stronę to skacze do 55-60, kolejne odświeżanie widzi jak skacze do 65-70MB.

Na normalnej stronie w obiegu pracy waha się między 45-65 (czasami 75 w zależności od tego, co robisz). Kliknięcie i wykonywanie przepływu pracy ze strony na stronę powoduje, że pamięć wzrasta do 85-100 i zwiększa się w miarę przechodzenia przez witrynę.

Próbowałem zrobić kilka rzeczy jak sprawdzić:

  • detacted węzły
  • heap snapshots & looking at The deltas
  • Amix ' s MemoryLeakChecker sprawdzający rozmiar obiektów
Potrzebowałbym głębszego nurkowania, aby szukać odniesień okrągłych lub problemów z zamknięciem.

Migawki sterty nie ujawniają zbyt wiele, większość top list to (array), (string), (system). Migawki mają rozmiar 4,8 MB, 5,1 MB,5,8 MB, 6,8 MB i więcej.

Mam kilka pytań jako wynik:

  • How do I understand the different metrics between snapshot memory and task manager memory
  • Are there any good tutorials (apart from the ones on the Google Developers site)?
  • How much memory is considered acceptable? Given in the task manager my site is always the highest?
  • Do I have a memory leak? Apart from the steps I've described above (which I haven't found anything concrete from) is there any other ways I can find leaks?
  • Can you suggest any tools apart from the Chrome Dev Tools (a lot of the tools mentioned on Google for Firefox are not compatible with the latest version, eg: Leak Monitor for FF)

Na marginesie, większość moich funkcji to operacje o niskim kluczu i nie przekraczają 200ms(w oparciu o profil procesora). Jaki jest dobry benchmark, do którego powinienem dążyć? Czy 200ms jest wysokie?

Author: Dominic, 2013-01-05

2 answers

To, co opisujesz, nie jest wyciekiem pamięci, to śmieci, o których wie Chrome i które zostaną usunięte, gdy Chrome zdecyduje, że nadszedł czas, aby to zrobić. Aby to wyjaśnić, przyjrzyjmy się bliżej opisanemu scenariuszowi.

Tworzenie pamięci do "wycieku"

  • najpierw otwórzmy nowe okno incognito (aby mieć pewność, że rozszerzenia przeglądarki nie wpływają na nasze wyniki) i przejdź do google.com.
  • następnie, pozwala otworzyć Menedżera zadań i włączyć " JavaScript Kolumna pamięć " (klikając prawym przyciskiem myszy na oknie Menedżera zadań). Potrzebujemy tej kolumny, aby mieć pewność, że pamięć, którą będziemy "wyciekać", jest w rzeczywistości alokowana przez JavaScript. Kończymy z czymś takim:

Pierwsze obciążenie

  • Teraz, tak jak sugerowałeś, powinniśmy przeładować stronę kilka razy i obserwować pamięć naszej karty w górę:

Po przeładowaniu 5+

Jak na razie dobrze - wszystko działa dokładnie tak, jak to opisałeś.

Wait a drugi...

Jednak pozostaw kursor nieaktywny przez pół minuty lub przejdź do innej karty, a zauważysz ogromny spadek zużycia pamięci na naszej karcie: google. Dlaczego? Co tam się stało? Kto wyczyścił nam "wyciekającą" pamięć?

Spadek Wykorzystania Pamięci

Aby to zbadać, powtórzmy to, co zrobiliśmy do tej pory, tak że 'Tab: google' znowu zużywa dużo pamięci. Następnie otwórz Narzędzia programistyczne Chrome i rozpocznij nagrywanie na karcie "oś czasu". Po tym, pozwala zmienić zakładka na kilka sekund, a gdy pamięć spadnie, Zatrzymaj "nagrywanie" na "osi czasu". Powinieneś skończyć z tym:

Tutaj wpisz opis obrazka

W ostatnich sekundach naszego nagrania pojawiły się tajemnicze "GC Events". Dokładnie w tym samym czasie, kiedy pamięć została uwolniona. Zbieg okoliczności? Nie.

GC Events

GC oznacza Garbage Collector . Jest to mechanizm, który " próbuje odzyskać śmieci, czyli pamięć zajmowaną przez obiekty, które nie są już używane przez program". Okazuje się więc, że pamięć naszej karty została zanieczyszczona śmieciami i GC był w stanie pozbyć się tych śmieci na cały czas (można nawet wymusić zbieranie śmieci za pomocą przycisku na dole zakładki 'Timeline'). Więc dlaczego zdecydował się tego nie robić? Dlaczego czekało, aż przestaniemy wchodzić w interakcję ze stroną lub zmienimy kartę?

Leniwy Śmieciarz

Krótka odpowiedź jest taka, że garbage collection musi "zamrozić" wykonanie wszystkich skryptów przed wykonaniem jakiejkolwiek pracy. Ponadto wykonanie może zająć znaczną ilość czasu procesora. Może to skutkować opóźnieniami, wzburzonymi animacjami, nie reagującymi kontrolkami itp. Dlatego Chrome czeka na odpowiedni moment , aby zadzwonić do garbage collection. A najlepszym momentem na to jest, gdy użytkownik nie patrzy.

Ponadto, należy pamiętać, że "GC Events" są seryjnie, zawsze jest kilka z nich z krótkimi przerwami pomiędzy. Te przerwy są przeznaczone do "normalnego" JavaScript do wykonania co garbage collection mniej zauważalne.

Żywe Obiekty

Spójrz na zakładkę" JavaScript Memory " na górze dwóch zrzutów ekranu w tym poście ponownie. Zauważysz, że ta kolumna zawiera dwie liczby. Pierwszym z nich jest pamięć " zarezerwowana dla JavaScript VM sterty", drugi to " ile pamięci żyje (osiągalne) obiekty include " ( source ). Podczas benchmarkingu aplikacji powinieneś martwić się tylko o drugą wartość, cała reszta będzie obsługiwana przez GC.

Przykład leak

Prawdziwy wyciek JavaScript może się zdarzyć ie. w aplikacji Web chat. Jeśli z czasem będzie on zużywał coraz więcej pamięci "na żywo", wyświetlając zawsze tylko ostatnie 10 wiadomości , to możemy mówić o wycieku. Taki wyciek, w końcu zawiesi kartę (lub przeglądarkę).

Podsumowanie

W przypadku skryptów uruchomionych na stronie, ponowne załadowanie strony (lub przejście do innej lokalizacji)jest równe ponownemu uruchomieniu komputera podczas pracy aplikacji ANSI C. Po tym, powinieneś pomyśleć o całej pamięci przydzielonej przez twoje Skrypty jako wymazane. Jedynym powodem, dla którego w praktyce może to nie nastąpić od razu po przeładowaniu strony, jest to, że przeglądarka czeka na odpowiedni moment, aby oczyścić. I Ty, jako twórca stron internetowych, nie powinieneś się tym martwić.

 35
Author: Konrad Dzwinel,
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-09-15 10:34:36

Jeśli nadal uważasz, że Twoja strona przecieka, możesz użyć odpowiedzi z tego pytania, aby wyśledzić wyciekające obiekty.

 1
Author: loislo,
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
2017-05-23 10:30:18