Как исправить рост памяти браузера при использовании периодических вызовов AJAX/XMLHttpRequest?

Я провел весь уик-энд, чтобы выяснить проблему роста памяти в своем веб-приложении, написанном в Dojo.

Веб-приложение будет запускаться навсегда, поэтому перезапуск браузера не планируется.

Приложение обновляет динамические данные с сервера (без перекрестного домена) на регулярной основе; каждые 5 секунд выполняется вызов AJAX для извлечения новых данных как JSON.

Позволяя приложению работать в течение нескольких часов, я наблюдал постоянный рост в памяти браузера (как на последних Chrome, так и на Firefox, как на последних Windows, так и на Mac OS X).

Сначала я думал, что Dojo вызывает такое поведение. И действительно, переключившись на собственную реализацию с объектом XMLHttpRequest, я мог резко сократить объем памяти, но он все еще существует. С каждым запросом AJAX память растет немного (около 4-8 КБ).

Что я уже пробовал:

У меня есть...

  • ... пытался использовать другие фреймворки, такие как jQuery, YUI и т.д. - no effect
  • ... перешел на использование собственного объекта XMLHttpRequest - помог много, но не полностью
  • ... деактивированное манипулирование DOM после получения данных - без эффекта
  • ... сбросил `xhr`, установив "null" и удалив его после каждой итерации - no effect
  • ... сбросил обработчик onreadystatechange до нулевого или пустого метода после каждой итерации - no effect
  • ... повторно использовал объект `xhr` и обработчик` onreadystatechange`, поскольку он всегда один и тот же - без эффекта

Итак, даже если я ничего не делаю (как описано в первой ссылке StackOverflow ниже) с загруженными данными, использование памяти увеличивается:

Что я уже читал:

Мой тестовый HTML-код:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Native XHR Async</title>
</head>
<body>
<script>

var update = document.createElement("div");
document.body.appendChild(update);

var timeout = null;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = onReadyState;

function loadData()
{
    xhr.open("GET","memory-leak.json?" + new Date().getTime());
    xhr.send(null);
}

function onReadyState()
{
   if (this.readyState === 4)
   {
       if( this.status === 200 )
       {
           update.innerHTML = "";
           update.innerHTML = this.responseText;
       }

       if( timeout !== null )
       {
           clearTimeout(timeout);
           delete timeout;
       }

       timeout = setTimeout(loadData, 1000);
   }       
}

loadData();

</script>

</body>
</html>

И мой тестовый JSON (в том же каталоге):

{
    "errorstatus":"Okay",
    "B0":{"P":"0 Watt"},
    "E0":{"P":"28 Watt"},
    "Z0":{"P":"28 Watt"},
    "S0":{"P":"0 Watt","SOC":"74%"},
    "Z1":{"P":"0 Watt"},
    "R0":0,
    "R1":0,
    "R2":0,
    "date":"29.09.2012 09:23:19",
    "Version":"Sep 28 2012-15.22"
}

У меня нет объяснений по этой проблеме, поэтому любая помощь очень ценится. Если вам нужна дополнительная информация об этом, пожалуйста, не стесняйтесь спрашивать меня.

Ответ 1

XmlHttpRequest будет кэшировать каждый ответ, поэтому вы добавляете дату, чтобы сделать URL уникальным.

Кэш записывается на диск как обычно, но также будет храниться в XmlHttpRequest, который сделал запрос до тех пор, пока он существует.

Вы должны использовать экземпляр для запроса и уничтожить его, или иначе убедиться, что кеширование отключено с помощью настроек pragmas и xhr.