Добавление элементов DOM с помощью jquery append () приводит к утечке памяти? - PullRequest
6 голосов
/ 12 ноября 2010

Только что встретился с клиентом, у которого огромные проблемы с утечкой памяти в их веб-приложении Ajax.Поэтому я решил создать следующий тестовый пример, чтобы продемонстрировать проблему:

Я использовал drip / Sieve для профилирования памяти в приведенном ниже примере (http://home.orange.nl/jsrosman/)

Случай прост: у меня есть следующий 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>

Каждый щелчок по заполненному списку добавляет 10000 элементов li (представленных в виде текста). Clearlist вызывает jquery empty (), который предположительно должен очистить поддерево DOM и сделать его подходящим для GC.

Таким образом, я запускаю этот случай в sIEve, и каждый раз, когда я добавляю новые элементы, потребление памяти увеличивается, я никогда не видел, чтобы он занимался сборкой мусора или освобождением памяти, даже когда использование оперативной памяти достигает 1,5 ГБ, и хотя я пытаюсь явно вызвать GC для IE.

Это тот же симптом, который я видел у клиента, который использовал Jquery Ajax для данных List вместо моего статического содержимого obv.

Я создаю DOM неверным способом? Может кто-нибудь?скажите мне, почему это не сборщик мусора, я не вижу никаких других ссылок на элементы DOM относительно того, почему они не должны быть garbagсобрал.Другое странное поведение заключается в том, что иногда использование sIEve-памяти даже увеличивается, когда я щелкаю пустой список (когда вызывается метод jquery empty ())?

Если у кого-нибудь есть входные данные, я был бы ОЧЕНЬ счастлив.

ОБНОВЛЕНИЕ, я попытался использовать $ ('# listparent'). Html ("") вместо этого, который, кажется, правильно выпускает DOM, по крайней мере, он выпускается в sIEve.Я думаю, что это лучшее решение, хотя у меня нет объяснения, почему remove () и empty () не работают.Может быть, они работают только для статически добавленных элементов?

Ответы [ 3 ]

1 голос
/ 12 ноября 2010

Я предлагаю добавить к строке HTML и затем добавить ее в DOM:

function populatelist() {
    for (var i = 0; i < 10000; i++) {
        //$('#listparent').append(lihtml);
        lihtml += "<li class='green'>this is a test text</li>";
    }    
}    
populateList();
$('#listparent').append(lihtml);
1 голос
/ 12 ноября 2010

да, вы могли бы добиться огромного улучшения, сделав что-то вроде этого

var lihtml = "<li class='green'>this is a test text</li>",
    listring = "";

function populatelist() {
        for (var i = 0; i < 10000; i++) {
            listring += lihtml;
        }    

        $('#listparent').append(listring);

    }    
...

ограничить доступ к DOM как можно меньше.

Разница в том, что вы делаете 1 одно добавление вместо 10 тысячприсоединяет.Вам всегда нужно избегать манипуляций с DOM внутри циклов

Редактировать: вместо пустого () вашего ul вы пытались удалить () ul, а затем внезапно воссоздать его?

0 голосов
/ 12 ноября 2010
$('#listparent').html(""); 

работает там, где не работали empty () или remove (). Хотел бы я знать почему. Я думаю, что это решение, хотя.

/ * На сегодня это самый эффективный способ освобождения памяти * /

function clearlist() {
    $('#listparent').html("");
    if (typeof (CollectGarbage) == "function") {
        alert('gc');
        CollectGarbage();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...