Appena incontrato un cliente che ha enormi problemi di perdita di memoria nella sua app web Ajax. Così ho deciso di creare la seguente testcase per dimostrare il problema:L'aggiunta di elementi DOM con jquery append() sembra perdere memoria?
ho usato a goccia/Sieve per il profiling di memoria nell'esempio che segue (http://home.orange.nl/jsrosman/)
Il caso è semplice: ho il seguente 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>
Ogni cliccare sul elenco popola aggiunge i 10000 elementi li (rappresentato come testo). Clearlist chiama jquery empty() che presumibilmente dovrebbe cancellare la sottostruttura DOM e renderla idonea per GC.
Così eseguo questo caso in SIEVOLE e per ogni volta che aggiungo nuovi elementi l'utilizzo della memoria aumenta, non l'ho mai visto raccolta di dati inutili o memoria libera. Neanche quando l'utilizzo della RAM raggiunge 1,5 GB e anche se provo a chiamare GC esplicitamente per IE.
Questo è lo stesso sympton che ho visto dal cliente che ha utilizzato Jquery Ajax per i dati dell'elenco invece del mio contenuto statico obv.
Sto creando il DOM nel modo sbagliato? Qualcuno può dirmi perché non si tratta di garbage collection, non riesco a vedere nessun altro riferimento agli elementi DOM sul motivo per cui non dovrebbero essere raccolti. Un altro strano comportamento è che a volte in uso la memoria aumenta anche quando faccio clic sulla lista vuota (quando viene chiamato il metodo jquery empty())?
Se qualcuno ha inserito sarei MOLTO felice.
UPDATE, ho provato a utilizzare $ ('# listparent'). Html ("") invece che sembra rilasciare correttamente il DOM, almeno è stato rilasciato in sIEve. Immagino che sia la soluzione migliore finora, anche se non ho alcuna spiegazione sul perché remove() e empty() non sembrano funzionare. Forse funzionano solo per elementi aggiunti staticamente?
solo curioso, hai provato questo in più browser? – Prescott
No sIEVE funziona solo in IE, non ho provato FFX, principalmente perché IE è l'unico browser utilizzato dagli utenti in questo sistema. – user408346
In realtà $ ('# listparent').html (""); funziona molto meglio di entrambi empty() e remove() e sembra rilasciare l'intero DOM. Sono senza parole – user408346