Po prostu spotkałem się z klientem, który ma ogromne problemy z wyciekiem pamięci w swojej aplikacji internetowej Ajax. Więc postanowiłem utworzyć następujący testcase wykazać problem:Dodanie elementów DOM z jquery append() wydaje się przeciekać pamięć?
Użyłem kroplówka/Sito do profilowania pamięci w poniższym przykładzie (http://home.orange.nl/jsrosman/)
The Przypadek jest prosty: Mam następujący javascript:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js">
</script>
</head>
<script type="text/javascript">
var lihtml = "<li class='green'>this is a test text</li>";
function populatelist() {
for (var i = 0; i < 10000; i++) {
$('#listparent').append(lihtml);
}
}
function clearlist() {
$('#listparent').empty();
if (typeof (CollectGarbage) == "function") {
alert('gc');
CollectGarbage();
}
}
/* Alternative clearlist with Remove instead of Empty(), still leaks */
function clearlist() {
/* test remove the parent itself instead of empty below */
$('#listparent').remove();
$('body').append("<ul id='listparent'>");
//$('#listparent').empty();
if (typeof (CollectGarbage) == "function") {
alert('gc');
CollectGarbage();
}
}
/* Edit!, this is the most effective way to release memory so far */
function clearlist() {
$('#listparent').html("");
if (typeof (CollectGarbage) == "function") {
alert('gc');
CollectGarbage();
}
}
</html>
</script>
<body>
<button onclick="javascript:populatelist()">Populate list</button>
<button onclick="javascript:clearlist()">Clear list</button>
<ul id="listparent">
<li>kjjk</li>
</ul>
</body>
</html>
Każde kliknięcie na liście wypełnia dołącza 10000 elementów li (reprezentowanych jako tekst). Lista jawna wywołuje jQuery puste(), które rzekomo powinno wyczyścić poddrzewo DOM i sprawić, by kwalifikowało się ono do GC.
Tak więc uruchamiam tę sprawę w SIEVE i za każdym razem, gdy dołączam nowe elementy, zużycie pamięci wzrasta, nigdy nie widziałem, aby to było zbędne lub wolna pamięć. Nawet wtedy, gdy użycie pamięci RAM osiąga 1,5 GB i mimo, że próbuję wywoływać GC jawnie dla IE.
To jest ten sam sympton, który widziałem u klienta, który używał Ajax Jquery dla danych listy zamiast mojej statycznej zawartości obv.
Czy tworzę DOM w niewłaściwy sposób? Czy ktokolwiek może mi powiedzieć, dlaczego nie zbiera śmieci, nie widzę żadnych innych odniesień do elementów DOM, dlaczego nie powinny być zbierane śmieci. Kolejne dziwne zachowanie polega na tym, że czasami użycie pamięci SIEve wzrasta nawet wtedy, gdy klikam pustą listę (gdy wywoływana jest metoda jquery empty())?
Jeśli ktokolwiek ma dane, byłbym BARDZO szczęśliwy.
AKTUALIZACJA, próbowałem za pomocą $ ('# listparent'). Html ("") zamiast, który wydaje się wydawać DOM poprawnie, przynajmniej jest wydany w sIEve. Sądzę, że to najlepsze rozwiązanie, chociaż nie mam żadnego wyjaśnienia, dlaczego remove() i empty() nie działają. Może pracują tylko dla statycznie dodanych elementów?
tylko ciekaw, czy próbowałeś to w wielu przeglądarkach? – Prescott
Żadne sIEve działa tylko w IE, nie próbowałem FFX, głównie dlatego, że IE jest jedyną używaną przeglądarką przez użytkowników w tym systemie. – user408346
Właściwie $ ('# listparent').html (""); działa znacznie lepiej niż puste() i remove() i wydaje się wypuścić cały DOM. Zaniemówiłam. – user408346