Podczas testowania naszej biblioteki JavaScript uważam, że znaleźliśmy poważny wyciek pamięci w IE10 (v10.0.9200.16519 - Windows 8 64 bit) Implementacja JavaScript setInterval
.Obejście problemu wycieku pamięci setInterval
Prosty przypadek testowy pokazał, że jeśli zmienna jest przechwytywana w zamknięciu funkcji, która jest przekazywana jako argument do późniejszego wykonania, nie wydaje się, aby kiedykolwiek była uprawniona do zbierania śmieci, tzn. Przeglądarka nadal wydaje się zawierać odniesienie do funkcji lub co najmniej zmiennych zamknięcia.
Nasza testcase uruchamia funkcję setInterval
tylko raz, a następnie czyści licznik interwału, tzn. Po chwili nie jest już wykonywany żaden kod i nie są już dostępne żadne zmienne (o ile widzę, żadne globale nie są wprowadzane w tym kodzie, z wyjątkiem dla metody do uruchomienia w onload
), mimo to proces zajmuje pół gigabajta pamięci (w zależności od liczby iteracji).
Co ciekawe to nie nastąpi, jeśli używamy metody setTimeout
zamiast (a także problem robi nie wydają się istnieć w IE9 i aktualne wersje Chrome, FF).
Problem można zobaczyć pod numerem this fiddle.
Uruchom go w świeżej instancji IE10 na Windows 8 i otwórz menedżera zadań, aby obejrzeć wykorzystanie pamięci. Szybko wzrośnie do 350 megabajtów i pozostanie tam po wykonaniu skryptu.
Jest to ważna część problematycznej kawałka kodu:
// the function that when called multiple times will cause the leak in IE10
var eatMemory = function() {
var a = null; // the captured closure variable
var intervalId = setInterval(function() {
a = createBigArray(); // call a method that allocates a lot of memory
clearInterval(intervalId); // stop the interval timer
}, 100);
}
(wiem, że to jest łatwe do naprawienia tego konkretnego kawałek kodu Ale to nie o to chodzi - to tylko najmniejsze. kawałek kodu, który wymyśliliśmy, który odwzorowuje problem, prawdziwy kod faktycznie przechwytuje w zamknięciu this
, a obiekt ten nigdy nie jest zbierany śmieci.)
Czy jest jakiś błąd w naszym kodzie lub czy istnieje sposób użycia setInterval
gdzie zmienna zamknięcia zawiera odniesienie do al arge obiekt bez wyzwalania wycieku pamięci i bez przywracania połączeń "rekursywnych" setTimeout
?
(ja również posted the question on MSDN)
Aktualizacja: Ten problem występuje również w IE10 na Windows 7, ale nie istnieje po przełączeniu na tryb IE9 standardów. Przesłałem to do MS Connect i poinformuję o postępach.
Aktualizacja: Microsoft accepted the issue i poinformował go, który zostanie ustalony w IE11 (wersja preview) - ja nie potwierdziły ten sam, jeszcze
Aktualizacja: IE 11 został oficjalnie wydany (ktoś?) i nie mogę odtworzyć problemu w tej wersji z moim systemem (Win 8.1 Pro 64bit).
Czemu tworząc odstęp, a następnie wyczyszczenie go natychmiast ? Czy to nie jest celem? –
@BradM Uaktualniłem pytanie z wyjaśnieniem - prawdziwy kod jest bardziej skomplikowany i nie zawsze bezwarunkowo kasuje ten interwał. – Sebastian
Czy próbowałeś nie używać funkcji anonimowej, ale zamiast tego referencji funkcji - a następnie jawnie nadpisujesz to odwołanie? – CBroe