Jak zniszczyć obiekt JavaScript?

81

Niedawno natknąłem się na jedną z moich aplikacji, która zużywa zbyt dużo pamięci i zwiększa się o 10 MB / s.

Dlatego chciałbym wiedzieć, jak najlepiej zniszczyć obiekt JavaScript i zmienne, aby zużycie pamięci pozostało na niskim poziomie, a mój FF nie został zniszczony.

Wywołuję dwa moje JavaScript co 8 sekund bez ponownego ładowania strony.

function refresh() {
    $('#table_info').remove();
    $('#table').hide();
    if (refreshTimer) {
        clearTimeout(refreshTimer);
        refreshTimer = null ;
    }
    document.getElementById('refresh_topology').disabled=true; 
    $('<div id="preload_xml"></div>').html('<img src="pic/dataload.gif" alt="loading data" /><h3>Loading Data...</h3>').prependTo($("#td_123"));
    $("#topo").hide();
    $('#root').remove();
    show_topology();
}

Jak mogę sprawdzić, która zmienna powoduje obciążenie pamięci i metodę, aby zatrzymać wykonywanie tego procesu?

Amit Shah
źródło
1
Czy rozważałeś wyodrębnienie części swoich kodów za pomocą domknięć?
YS.
1
Próbowałeś czegoś? Lubisz używać obj = null?
Florian Margaine
A) Co robi show_topology? --- B) Czy kiedykolwiek usuwasz rzeczy, do których dodajesz #td_123? --- C) Czy jest gdzieś dostępna wersja na żywo?
Deestan

Odpowiedzi:

93

Możesz umieścić cały kod w jednej przestrzeni nazw w ten sposób:

var namespace = {};

namespace.someClassObj = {};

delete namespace.someClassObj;

Użycie deletesłowa kluczowego spowoduje usunięcie odniesienia do właściwości, ale na niskim poziomie moduł odśmiecania pamięci JavaScript (GC) uzyska więcej informacji o obiektach do odzyskania.

Możesz również użyć Narzędzi dla programistów Chrome, aby uzyskać profil pamięci swojej aplikacji i określić, które obiekty w aplikacji wymagają zmniejszenia.

Yochai Akoka
źródło
12
Naciśnij klawisz F12, aby uzyskać narzędzia programistyczne. Przejdź do zakładki Profil i kliknij Start, aby uruchomić profil. Możesz wykonać profilowanie na procesorze JS, selektorze CSS i możesz wykonać migawkę sterty.
Sarath
3
lub w najnowszym chrome wpisz słowo performance w konsoli js
David Morrow
Być może jest to oczywiste, ale możesz nazwać swoją przestrzeń nazw na przykład „g” i zaoszczędzić wiele wpisywania. Użyj g.curItem = ... zamiast var curItem = ... i zapisz wpisywanie, a także pozwól, aby g = undefined wyczyścił całą globalną alokację pamięci.
David Spector,
31

Nie możesz usunąć obiektów, są one usuwane, gdy nie ma już do nich odniesień. Możesz usunąć odniesienia za pomocą delete.

Jednakże, jeśli utworzyłeś cykliczne odniesienia w swoich obiektach, być może będziesz musiał odłączyć niektóre rzeczy.

CodeClown42
źródło
2
Czy mógłbyś dodać przykład cyklicznej referencji, która nie została przechwycona przez moduł odśmiecania pamięci? Pytanie o przyjaciela! ;)
emilhem
@emilhem możesz odwołać się do garbage collectora, a on usunie siebie i Internet - implozja prawdopodobnie stworzy czarną dziurę w CERN. Czy myślałeś o tym przykładzie?
El Mac
28

Podczas gdy dotychczasowe odpowiedzi podały rozwiązania problemu i drugiej połowy pytania, nie dają odpowiedzi na aspekt samopoznania w pierwszej połowie pytania, które jest pogrubione:

„Jak mogę sprawdzić, która zmienna powoduje obciążenie pamięci ...?”

Być może 3 lata temu nie było tak solidne, ale sekcja „ Profile ” narzędzi programistycznych Chrome jest teraz dość potężna i bogata w funkcje. Zespół Chrome ma wnikliwy artykuł na temat korzystania z niego, a tym samym również tego, jak działa odzyskiwanie pamięci (GC) w javascript, który jest u podstaw tego pytania.

Ponieważ deletejest to w zasadzie źródło aktualnie akceptowanej odpowiedzi Yochai Akoki, ważne jest, aby pamiętać, co robi usuwanie. Jest to nieistotne, jeśli nie jest połączone z koncepcjami działania GC w następnych dwóch odpowiedziach: jeśli istnieje istniejące odniesienie do obiektu, nie jest ono czyszczone. Odpowiedzi są bardziej poprawne, ale prawdopodobnie nie tak cenione, ponieważ wymagają więcej przemyślenia niż zwykłe napisanie „usuń”. Tak, jednym możliwym rozwiązaniem może być użycie delete, ale nie będzie miało znaczenia, czy istnieje inne odniesienie do wycieku pamięci.

Inna odpowiedź odpowiednio wspomina o cyklicznych odniesieniach, a dokumentacja zespołu Chrome może zapewnić znacznie większą przejrzystość, a także narzędzia do weryfikacji przyczyny.

Ponieważ deletewspomniano tutaj, przydatne może być również udostępnienie zasobu Omówienie usuwania . Chociaż nie wchodzi w żadne rzeczywiste rozwiązanie, które jest naprawdę związane z garbage collectorem javascript.

Shwaydogg
źródło
9

Skonstruuj swój kod tak, aby wszystkie tymczasowe obiekty znajdowały się wewnątrz zamknięć zamiast globalnych właściwości przestrzeni nazw / globalnych obiektów, a gdy skończysz z nimi, wyjdą poza zakres. GC zajmie się resztą.

Oleg V. Volkov
źródło
1

Miałem do czynienia z takim problemem i wpadłem na pomysł, aby po prostu zmienić innerHTML dzieci problematycznego obiektu.

adiv.innerHTML = "<div...> the original html that js uses </div>";

Niby brudny, ale uratował mi życie, bo działa!

Sergio Abreu
źródło