Aync XMLHTTP with Javascript: memory problems

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Justice

    Aync XMLHTTP with Javascript: memory problems

    Currently I'm doing some experimenting with the XMLHTTP object in
    Javascript. Now,
    the XMLHttp object is asynchronous (at least in this case), and the
    following code causes a significant memory loss even though I seem to be
    allocaitng everything; help would be *vastly* appreciated. What am I doing
    wrong here? I thought I was doing everything correctly (setting things to
    null, for example) but none of the memory seems to get replaced. I've been
    experiencing allocations of memory up to 125 megabytes (!) that simply
    persist in the browser, never to go away...

    Thanks in advance for any help you can provide!

    ASyncQueue = new Array();
    -Justice
    function DataHandlerLook upLoop(value, id, numberOfLoops)

    {

    for (var loopCount = 0; loopCount < numberOfLoops; loopCount++)

    {

    DataHandlerLook up(loopCount,lo opCount,id);

    }

    }

    function DataHandlerLook up(value, number, id)

    {

    ++asyncsRunning ;

    AsyncQueue.push (new Object());

    AsyncQueue[number].ThisElement = document.getEle mentById(id);

    AsyncQueue[number].Server = new ActiveXObject(" Msxml2.XMLHTTP" );

    AsyncQueue[number].Server.onready statechange = f;

    AsyncQueue[number].Server.open("G ET",
    "http://localhost/MyCompany/data.metadata?t ext=" + value, true);

    AsyncQueue[number].Server.send(va lue);

    }



    function f()

    {

    var temporaryLength = AsyncQueue.leng th;

    for (var index = 0; index < AsyncQueue.leng th; ++index)

    {

    if (AsyncQueue[index] != null)

    {

    if (AsyncQueue[index].Server.readySt ate == FINISHED)

    {

    AsyncQueue[index].Server.abort() ;

    AsyncQueue[index].Server = null;

    delete AsyncQueue[index].Server;

    AsyncQueue[index].ThisElement = null;

    delete AsyncQueue[index].ThisElement;

    AsyncQueue[index] = null;

    --asyncsRunning;

    }

    if (asyncsRunning == 0)

    {

    var tempQueueLength = AsyncQueue.leng th;

    for (var ix = 0; ix < tempQueueLength ; ++ix)

    {

    AsyncQueue.pop( );

    }

    CollectGarbage( );

    }

    }





  • Steve van Dongen

    #2
    Re: Aync XMLHTTP with Javascript: memory problems

    On Fri, 28 Nov 2003 03:47:14 GMT, "Justice" <justice_gray@h otmail.com>
    wrote:
    [color=blue]
    >Currently I'm doing some experimenting with the XMLHTTP object in
    >Javascript. Now,
    >the XMLHttp object is asynchronous (at least in this case), and the
    >following code causes a significant memory loss even though I seem to be
    >allocaitng everything; help would be *vastly* appreciated. What am I doing
    >wrong here? I thought I was doing everything correctly (setting things to
    >null, for example) but none of the memory seems to get replaced. I've been
    >experiencing allocations of memory up to 125 megabytes (!) that simply
    >persist in the browser, never to go away...
    >[/color]
    <snip />

    Been there, done that.
    [color=blue]
    > AsyncQueue[index].Server.abort() ;
    >
    > AsyncQueue[index].Server = null;
    >
    > delete AsyncQueue[index].Server;
    >
    > AsyncQueue[index].ThisElement = null;
    >
    > delete AsyncQueue[index].ThisElement;
    >
    > AsyncQueue[index] = null;[/color]
    You don't need to call abort() or any of the 4 lines after that.
    [color=blue]
    > CollectGarbage( );[/color]
    CollectGarbage won't solve your problems. It is only useful in
    debugging as it forces the garbage collector to run at a known point.

    Aside from executing code too many times (the f() function is called 3
    times per HTTP request and you loop through each item in your array),
    there doesn't appear to be any problems noticable at first glance.
    But this isn't your actual code, is it? It doesn't make much sense to
    make HTTP requests but do nothing with the results....

    Regards,
    Steve

    Comment

    • Justice

      #3
      Re: Aync XMLHTTP with Javascript: memory problems


      "Steve van Dongen" <stevevd@hotmai l.com> wrote in message
      news:uk7gsvor9q 4res7ce6ellrt9b emtmhd8g7@4ax.c om...[color=blue]
      > Been there, done that.
      >[color=green]
      > > AsyncQueue[index].Server.abort() ;
      > >
      > > AsyncQueue[index].Server = null;
      > >
      > > delete AsyncQueue[index].Server;
      > >
      > > AsyncQueue[index].ThisElement = null;
      > >
      > > delete AsyncQueue[index].ThisElement;
      > >
      > > AsyncQueue[index] = null;[/color]
      > You don't need to call abort() or any of the 4 lines after that.[/color]
      [color=blue][color=green]
      > > CollectGarbage( );[/color]
      > CollectGarbage won't solve your problems. It is only useful in
      > debugging as it forces the garbage collector to run at a known point.[/color]

      I simply threw it in to see if memory was actually being deallocated.
      Unfortunately, nothing really changed.
      [color=blue]
      > Aside from executing code too many times (the f() function is called 3
      > times per HTTP request and you loop through each item in your array),[/color]

      How can I necessarily avoid calling f three times, however? Attaching f to
      onreadystatecha nge basically guarantees that this thing is going to get
      called every time.

      Ideally, I would have liked a way in "f" to determine which server object
      fired the onreadystatecha nge event, but no information comes back from
      onreadystatecha nge to indicate this, hence my convoluted attempts at
      resolving things.
      [color=blue]
      > there doesn't appear to be any problems noticable at first glance.
      > But this isn't your actual code, is it? It doesn't make much sense to
      > make HTTP requests but do nothing with the results....[/color]

      You're correct. However, even this code (without anything notable in
      function "f", which would do something w/ the results) leads to memory
      leaks. If I simulate an environment where, say, 400 of these requests are
      made, the memory piles up and piles up and eventually I have IE using 156
      megabytes of memory.

      Unfortunately, although there don't *seem* to be any problems noticeable
      (that's what I thought too, other than some semi-inefficient ways of going
      through the asynclist) the memory allocations for this are enormous when 200
      or so requests go through.

      Thanks for any insight you can provide,
      -Justice


      Comment

      • Steve van Dongen [MSFT]

        #4
        Re: Aync XMLHTTP with Javascript: memory problems

        On Sun, 30 Nov 2003 05:09:09 GMT, "Justice" <justice_gray@h otmail.com>
        wrote:
        [color=blue]
        >
        >"Steve van Dongen" <stevevd@hotmai l.com> wrote in message
        >news:uk7gsvor9 q4res7ce6ellrt9 bemtmhd8g7@4ax. com...[color=green]
        >> Been there, done that.
        >>[color=darkred]
        >> > AsyncQueue[index].Server.abort() ;
        >> >
        >> > AsyncQueue[index].Server = null;
        >> >
        >> > delete AsyncQueue[index].Server;
        >> >
        >> > AsyncQueue[index].ThisElement = null;
        >> >
        >> > delete AsyncQueue[index].ThisElement;
        >> >
        >> > AsyncQueue[index] = null;[/color]
        >> You don't need to call abort() or any of the 4 lines after that.[/color][/color]

        It looks like you may actually need to set .Server and .ThisElement =
        null though frankly I'm not sure why.
        [color=blue][color=green][color=darkred]
        >> > CollectGarbage( );[/color]
        >> CollectGarbage won't solve your problems. It is only useful in
        >> debugging as it forces the garbage collector to run at a known point.[/color]
        >
        >I simply threw it in to see if memory was actually being deallocated.
        >Unfortunatel y, nothing really changed.
        >[color=green]
        >> Aside from executing code too many times (the f() function is called 3
        >> times per HTTP request and you loop through each item in your array),[/color]
        >
        >How can I necessarily avoid calling f three times, however? Attaching f to
        >onreadystatech ange basically guarantees that this thing is going to get
        >called every time.
        >
        >Ideally, I would have liked a way in "f" to determine which server object
        >fired the onreadystatecha nge event, but no information comes back from
        >onreadystatech ange to indicate this, hence my convoluted attempts at
        >resolving things.[/color]

        See below.
        [color=blue][color=green]
        >> there doesn't appear to be any problems noticable at first glance.
        >> But this isn't your actual code, is it? It doesn't make much sense to
        >> make HTTP requests but do nothing with the results....[/color]
        >
        >You're correct. However, even this code (without anything notable in
        >function "f", which would do something w/ the results) leads to memory
        >leaks. If I simulate an environment where, say, 400 of these requests are
        >made, the memory piles up and piles up and eventually I have IE using 156
        >megabytes of memory.
        >
        >Unfortunatel y, although there don't *seem* to be any problems noticeable
        >(that's what I thought too, other than some semi-inefficient ways of going
        >through the asynclist) the memory allocations for this are enormous when 200
        >or so requests go through.[/color]

        Whenever you use nested functions, a closure is created, giving the
        enclosed function access to all of the outer function's arguments and
        local variables. This is a common source of memory leaks. The
        problem comes down to how relatively easy it is to create circular
        references when you don't realize what is really going on. The
        JScript garbage collector is capable of breaking circular references
        between any number of JScript objects, but it cannot break a circular
        reference where the chain includes an external object like an element
        in IE or a COM object.

        So, the point is basically, try not to mix nested functions and DHTML
        and/or ActiveX because you might end up with a circular reference that
        cannot be broken and, therefore, a memory leak.

        This is an example of a function that leaks memory...
        function omicron()
        {
        var x = MakeNewDiv();
        x.foo = epsilon;
        function epsilon()
        {
        ...
        }
        }
        The circular reference is:
        x --> div --> epsilon --> x

        That said, the only way to pass data to your onreadystatecha nge
        handler is to use a closure. This example doesn't leak...

        AsyncQueue = new Array();
        asyncsRunning = 0;

        function Init()
        {
        for (var i=0; i<500; i++)
        {
        AsyncRequestSta rt("", "id" + i);
        }
        }

        function AsyncRequestSta rt(value, id)
        {
        var index;
        var requestInfo = new Object();

        index = AsyncQueue.leng th;
        AsyncQueue.push (requestInfo);

        // requestInfo.Thi sElement = document.getEle mentById(id);
        requestInfo.Ser ver = new ActiveXObject(" Msxml2.XMLHTTP" );
        requestInfo.Ser ver.onreadystat echange = function () {
        AsyncRequestCom plete(index);
        };
        requestInfo.Ser ver.open("GET",
        "http://localhost/MyCompany/data.metadata?t ext=" + value, true);
        requestInfo.Ser ver.send(value) ;
        asyncsRunning++ ;
        }

        function AsyncRequestCom plete(index)
        {
        var requestInfo = AsyncQueue[index];
        Log(index + ": readyState=" + requestInfo.Ser ver.readyState) ;
        if (requestInfo.Se rver.readyState == 4 /*FINISHED*/)
        {
        asyncsRunning--;
        UpdateStatus();

        // requestInfo.Thi sElement = null;
        requestInfo.Ser ver = null;
        delete AsyncQueue[index];
        }
        requestInfo = null;
        }

        function Log(s)
        {
        window.status = s;
        }

        function UpdateStatus()
        {
        document.body.i nnerText = "Pending Requests: "
        + asyncsRunning;
        }

        Regards,
        Steve
        --
        Please post questions to the newsgroup; everyone benefits.
        This post is provided "AS IS" with no warranties, and confers no rights
        Sample code subject to http://www.microsoft.com/info/cpyright.htm

        Comment

        • Justice

          #5
          Re: Aync XMLHTTP with Javascript: memory problems


          "Steve van Dongen [MSFT]" <stevevd@online .microsoft.com> wrote in message
          news:33pjsvgjnf 07arnnpvf8f6lnq du2pdpr9q@4ax.c om...
          [color=blue]
          > It looks like you may actually need to set .Server and .ThisElement =
          > null though frankly I'm not sure why.[/color]

          I thought I had read something about references to the DOM causing leaks in
          other's applications. (Part of it is just my paranoia in Javascriptabout
          setting everything to null once I am done with the objects).

          [explanation of closures and circular references]
          See, I figured that *might* have been the problem and thus rearchitected
          things to pull "f" out of the closure. However, that still didn't do
          anything in terms of the memory usage. (see below where I reply to your
          example)
          [color=blue]
          > That said, the only way to pass data to your onreadystatecha nge
          > handler is to use a closure. This example doesn't leak...[/color]

          Thanks for your example! However, running your example through tresting and
          looking at IE's memoery usage before and after:


          IE before Init() is called:

          Physical Memory: 14944 K
          Peak Memory Usage: 14,944 K
          Virtual Memory: 6,640 K

          IE after Init() finishes:
          Physical Memory: 23,880 K
          Peak Memory Usage: 25,472 K
          Virtual Memory: 16,872 K

          And, just for kicks, I jacked up your Init function to loop 4,000 times
          instead of just 500. Here were my results after it finished:

          Physical Memory: 66,830 K
          Peak Memory Usage: 92,104 K
          Virtual Memory Usage: 73,104 K

          This memory usage does not go away until I close IE (it stays even when
          navigating to other sites). This is the memory leak I am referring to,
          which now you have caught as well!

          Therein lies my problem...?

          Thanks,

          -Justice


          Comment

          • Steve van Dongen [MSFT]

            #6
            Re: Aync XMLHTTP with Javascript: memory problems

            On Sun, 30 Nov 2003 18:20:15 GMT, "Justice" <justice_gray@h otmail.com>
            wrote:
            [color=blue]
            >
            >"Steve van Dongen [MSFT]" <stevevd@online .microsoft.com> wrote in message
            >news:33pjsvgjn f07arnnpvf8f6ln qdu2pdpr9q@4ax. com...
            >[color=green]
            >> That said, the only way to pass data to your onreadystatecha nge
            >> handler is to use a closure. This example doesn't leak...[/color]
            >
            >Thanks for your example! However, running your example through tresting and
            >looking at IE's memoery usage before and after:
            >
            >
            >IE before Init() is called:
            >
            >Physical Memory: 14944 K
            >Peak Memory Usage: 14,944 K
            >Virtual Memory: 6,640 K
            >
            >IE after Init() finishes:
            >Physical Memory: 23,880 K
            >Peak Memory Usage: 25,472 K
            >Virtual Memory: 16,872 K
            >
            >And, just for kicks, I jacked up your Init function to loop 4,000 times
            >instead of just 500. Here were my results after it finished:
            >
            >Physical Memory: 66,830 K
            >Peak Memory Usage: 92,104 K
            >Virtual Memory Usage: 73,104 K
            >
            >This memory usage does not go away until I close IE (it stays even when
            >navigating to other sites). This is the memory leak I am referring to,
            >which now you have caught as well![/color]

            Sounds like you're measuring at different states. Before Init() is
            called there are 0 pending requests; when Init() is complete there are
            500 (or 4000) pending requests. You have to measure when the pending
            request count reaches 0 again.

            When I was testing my code I found that when I refreshed the page the
            memory usage before and after was pretty consistent. Adding
            CollectGarbage( ) at the end made it a little more consistent which is
            what I'd expect. Another thing I noticed was that on the first run
            memory usage after all the requests had completed was higher than at
            the beginning. I suspect the discrepancy is the result of IE delay
            loading some libraries and not indicative of a memory leak caused by
            the script.

            Regards,
            Steve
            --
            Please post questions to the newsgroup; everyone benefits.
            This posting is provided "AS IS" with no warranties, and confers no rights.
            Sample code subject to http://www.microsoft.com/info/cpyright.htm

            Comment

            Working...