Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix browser's memory growth when using periodic AJAX/XMLHttpRequest calls?

I've spent the whole weekend to elaborate the memory growth issue within my web application written in Dojo.

The web application is going to "run forever", so restarting the browser is not planned.

The application is updating dynamic data from server (no cross domain) on a regular basis; each 5 seconds, an AJAX call is made to retrieve the new data as JSON.

By letting the application run for hours, I observed a constant growth in browser's memory (both on latest Chrome and Firefox, both on latest Windows and Mac OS X).

At first, I thought Dojo was causing this behaviour. And indeed, by switching to native implementation with the XMLHttpRequest object I could reduce the memory growth dramatically, but it still exists. With each AJAX request the memory is growing a little bit (about 4-8KB).

What I've already tried:

I have...

  • ...tried to use other frameworks such as jQuery, YUI, etc. - no effect
  • ...switched to using the native `XMLHttpRequest` object - helped a lot, but not entirely
  • ...deactivated DOM manipulation after retrieved data - no effect
  • ...resetted `xhr` by setting to `null` and deleting it after each iteration - no effect
  • ...resetted onreadystatechange handler to null or an empty method after each iteration - no effect
  • ...reused the `xhr` object and the `onreadystatechange` handler as it's always the same - no effect

So even if I do nothing (as also described in the first StackOverflow link below) with the loaded data, the memory usage increases:

What I've already read:

  • Memory Leak with an XMLHttpRequest and setInterval
  • Automatic web-page refresh memory leak using XMLHttpRequest
  • Memory-leak at a wrapped XMLHttpRequest function
  • http://forum.jquery.com/topic/memory-leaks-with-ajax-calls
  • and much more...

My test HTML code:

<!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>

And my test JSON (in the same directory):

{
    "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"
}

I don't have any explanation for this issue, so any help is much appreciated. If you need any further information about this, please don't hesitate to ask me.

like image 308
arm1n Avatar asked Oct 01 '12 12:10

arm1n


1 Answers

The XmlHttpRequest will cache each response which is why you're appending the date to make the URL unique.

The cache is written to disk as normal, but also will be held in an XmlHttpRequest which has made a request as long as it exists.

You should use an instance per request and destroy it, or otherwise make sure caching is disabled via pragmas and xhr settings.

like image 65
Rob Hardy Avatar answered Sep 28 '22 06:09

Rob Hardy