views:

90

answers:

1

Each ProcessingPayments() used memory increase. CollectGarbage() not helps. Use Drip to view memory usage, but don't view any DOM leaks.

I use only IE8 and tested on older versions. Other browsers not interested.

How can I decrease growing memory usage while execute this script?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
    <html xmlns="http://www.w3.org/1999/xhtml"&gt;
     <head>
      <title>JS IE XMLHTTP - Memory leaks</title>
     </head>

    <body onload="ProcessingPayments();locCollectGarbage();">

    <script language="JScript">
    var toProcessingPayments;
    var ProcessingPaymentsPeriod = 1*60*1000;
    var SessionCount = 1;
    var CollectGarbageCount = 1;


    function ProcessPayment(arrParams) {
     var e;
     var strURL = "http://www.facebook.com/";
     var strURLParam = "";
     try { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP.6.0"); }
     catch (e) { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP"); }

     function ProcessPaymentHTTPRequest() {
      if (locHTTPRequest.readyState != 4) {
       return;
      }

      if (locHTTPRequest.status != 200) {
       document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML
        +arrParams.i+" = error code "+locHTTPRequest.status+"<br />";

       return false;
      }

      if (locHTTPRequest.getResponseHeader("Content-Type").indexOf("text/html") < 0) {
       document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML
        +arrParams.i+" = wrong content type "+locHTTPRequest.getResponseHeader("Content-Type").indexOf("text/html")+"<br />";

       return false;
      }

      try {
        document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML
         +arrParams.i+" = processed<br />";

        return true;

      }
      catch(e) {
       if (locHTTPRequest.responseXML.parseError != 0) {
        return false;
       }
       else {
        return false;
       }
      }

      locHTTPRequest.abort();
      delete locHTTPRequest["onreadystatechange"];
      locHTTPRequest = null;
     } // function ProcessPaymentHTTPRequest()

     strURLParam = "?"+arrParams.i;

     locHTTPRequest.open("get", strURL+strURLParam);

     document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML
       +arrParams.i+" = request<br />";

     locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest;

     locHTTPRequest.send(null);
    }


    function ProcessingPayments(arrPayment) {
     var e;

     toProcessingPayments = null;

     document.getElementById("CurrentSession").innerHTML = "";

     for (var i = 0; i < 10; i++) {
      ProcessPayment({
       i:   i
      });
     }

     SessionCount++;

     document.getElementById("Session").innerText = SessionCount;

     toProcessingPayments = setTimeout(ProcessingPayments, ProcessingPaymentsPeriod);
    }


    function locCollectGarbage() {
     CollectGarbage();

     document.getElementById("CollectGarbage").innerText = CollectGarbageCount;

     CollectGarbageCount++;

     setTimeout(locCollectGarbage, 5*60*1000);
    }
    </script>
    </body>

    <p>Sessions: <span id="Session">0</span></p>
    <p>CollectGarbage(): <span id="CollectGarbage">0</span></p>
    <hr />
    <br />

    <p>Current session:</p>

    <p id="CurrentSession"></p>

    </html>
+1  A: 
locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest;

Creates a reference loop between a native-JScript object (the ProcessPaymentHTTPRequest function, which has the request object in scope) and a non-JScript object (the XMLHttpRequest ActiveX object). It is this kind of reference loop that makes IE fail to GC.

delete locHTTPRequest["onreadystatechange"];

Whilst that would be OK for a native JavaScript object, in reality delete doesn't actually work to remove an event handler from a DOM object. So the handler and reference loop remains in place. What is typically done instead is to overwrite the locHTTPRequest.onreadystatechange handler with a dud value, such as a predefined function that immediately returns, or '', or null. Or alternatively, use addEventListener/attachEvent and their corresponding remove-handler methods.

CollectGarbage();

What does that do? There's not really much you can do to influence GC from JS.

Aside:

<script language="JScript">

type="text/javascript" instead of language. I know you don't care about non-IE, but there seems little point in being gratuitous incompatible as well as non-standard.

 try { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP.6.0"); }
 catch (e) { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP"); }

There is no need to do this. You aren't using any features of the newer MSXML version, so just plump for unversioned XMLHttp. Also, go for native-JS XMLHttpRequest first. Not just because it exists on other browsers, but also because it's more efficient and, being native JS, doesn't cause memory leaks.

Best: add fallback for IE6:

if (!window.XMLHttpRequest && 'ActiveXObject' in window) {
    window.XMLHttpRequest= function() {
        return new ActiveXObject('MSXML2.XMLHttp');
    }
}

and then just use standard new XMLHttpRequest() everywhere.

locHTTPRequest.send(null);

This is non-standard even for IE. Omit the data argument if you don't want to send anything, rather than supplying null.

bobince
I cannot try use native XMLHttpRequest, because I get an error message "access is denied" (cross domain request, because this HTML based on local computer and URL located to facebook). All settings to prevent this error was made and with activex object XMLHttp cross domain works, but with builtin XMLHttpRequest doesn't work.
plr
I change code with your suggestions:1. change delete locHTTPRequest["onreadystatechange"];to locHTTPRequest.onreadystatechange = null;2. Disable CollectGarbage();3. <script language="JScript" type="text/javascript">4. locHTTPRequest.send();Run script in Drip and view memory growing while executing the same as in original variant.Any solutions?
plr