0 Replies Latest reply on Nov 2, 2012 8:24 AM by Steve Sutton

    Large Memory Usage With Javascript Closures Using Ajax

      Under certain circumstances Javascript will exibit behavour known as a closure, whereby an object that has been declared in an outer scope is not able to be garbage collected when a reference to it is held within an inner scope function which has gone out of scope itself.

       

      Originally Javascript intended this to keep instance data for separate objects without the need for additional steps to be taken. eg multiple threads or recursive functions.

       

      When itterative designs are implemented the effect can be the same as memory leak, ie. memory usage is increasing over time. In fact the memory is not leaked, but the working set requirement is increasing. Memory for referenced objects is increasing due to the closures created.

       

      When using Ajax (eg. XMLHttpRequest) and there are nested functions, it is possible to get the situation described above. An inner function holds a reference to the XMLHttpRequest object declaration in the outer function. This is not an issue when the number of itterations is small, but when the number of itterations becomes large, the memory usgae can significantly increase over time, giving the impression of memory leakage.In reality the memory is being used to hold references to objects that are not needed and therefore increasing the working set for the process. When the process terminates the memory will be released via garbage collection.

       

      In the example below, the memory usage will increase over time if makeLeak() is called many times.

       

      function makeLeak()

        {

              //

             // Effectively becomes a static as inner function holds a reference to it

             //

            var xhr = new XMLHttpRequest();

             xhr.onreadystatechange = function (event)

            {

               // Inner function - holds reference to XMLHttpRequest object in the

              // Outer function when this function goes out of scope the

       

            // XMLHttpRequest instance is orphaned as there is a reference

            // still remaining

             if (xhr.readyState == 4 && xhr.status == 200)

             {

                    ... do something

             }

         };

      }

       

      In order to avoid issue, the reference to the object in the closure is set to null when no longer required. Now the garbage collector
      will be able to destroy the objects and therefore reduce the memory usage as far as possible. See revised function below:

       

      function makeLeak()

      {

        var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = function (event)

        {

            if (xhr.readyState == 4 && xhr.status == 200)

            {

                // Help the garbage collector to clean up by nulling out

                // the function and object pointers.

                xhr.onreadystatechange = new Function; //empty function

                xhr = null;

                ... do something

            }

         };

      }

       

      Reference:    http://phptouch.com/2011/08/02/xmlhttprequest-leak-in-ie-78/