<< Перестал работать hibernate | На главную | Пингвины, пингвины... >>

Ajax и утечки памяти в IE

Ajax and memory leaks at IE

На днях был один фриланс, надо было разобраться почему в библиотечке для javascript использующей ajax имеются утечки памяти при работе в осле.
Вообще javascript не предоставляет особой работы с памятью и должен все подчищать сам за собой.
Посмотрим простой пример работы с XMLHttpRequest:

var count = 0;
function getHttpRequest() {
    httpRequest = false;
    if (window.XMLHttpRequest) { // Mozilla, Safari,...
        httpRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // IE
        try {
            httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {}
        }
    }
    return httpRequest;
}
 
function getServerData() {
    var _request = getHttpRequest();
 
    _request.onreadystatechange = function() {
        if (_request.readyState == 4 && _request.status == 200) {
            document.getElementById('content').innerHTML = count + "<br/>" + _request.responseText;
            count ++;
        }
    }
    _request.open("GET", "test.txt", true);
    _request.send(null);
}
function run() {
    getServerData();
    setTimeout('run()', 100);   
}

А где-то там в html-коде вызывается что-то типа onload="run()". Не трудно заметить что 10 раз в секунду этот скрипт будет обращаться к страничке и выводить ее сообщение на экран, кроме этого он будет писать число обращений к этой страничке.
Открываем теперь эту страничку в Internet Explorer и смотрим что будет происходить с памятью.

Для простоты я ее разместил у себя на сервачке: http://www.nik0las.ru/blog/files/2009/ajax/bad.html.

После того как я откупорил в своем осле (кстати ради этого даже загрузил, о ужас, венду!) он начал интенсивно пожирать память. Вот график того, сколько он скушал памяти за пару сотен запросов:

IE ajax memory leak

Как показало гугление, это довольно известная шняга в ослине. И встречается не только при работе с аяксом, но и в других случаях. Вот пара ссылочек по теме:

http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector.aspx
http://www.codeproject.com/KB/scripting/leakpatterns.aspx

В двух словая суть процесса такова. Создается два обьекта, один в javascript, а второй в ActiveX, и имеют кросс ссылки друг на друга, и поэтому гарбадж коллекторы не могут нормально удалить эти обьекты. Решение очень простое - удаляем обьект из javascript принудительно.

Для этого надо добавить всего лишь одну строчку в наш код:
if (_request.readyState == 4 && _request.status == 200) {
    document.getElementById('content').innerHTML = count + "<br/>" + _request.responseText;
    count ++;
    _requset = null;
}


Вот ссылка на исправленный код:
http://www.nik0las.ru/blog/files/2009/ajax/good.html

И картинка расхода памяти на 1к запросов:
IE ajax memory leak: fixed

Как легко увидеть ничего не течет.

Добавлено 17.06.2009.
Все это верно для версий IE меньше 7, причем говорят что в последней версии 6-го тоже исправлено.

Ярлыки : , ,


Re: Ajax и утечки памяти в IE

Спасибо, Колян :)

Немного подправил свой скриптег. :)

Комментировать