Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this AJAX pattern a memory leak?

Consider this example of pretty standard method in Angular Js, which updates the view:

$scope.fetchResults = function() {
    // Some local variable that will cause creation of closure
    var hugeData = serviceX.getMilionRecords();

    // Any call to any resource with success and error handlers.
    $http({
        method: "GET",
        url: "/rest-api/bulk-operation-x",
        params: { someParam: hugeData.length }

    }).success( function () {
        var length = hugeData.length;
        $scope.reportToUser("Success, that was " + length + " records being processed!";

    }).error( function () {
        var length = hugeData.length;
        $scope.reportToUser("Something went wrong while processing " + length + " records... :-(";
    });
};

This is of course hypothetical example, but it nicely shows pattern, which could be described as reusing of local variables from within AJAX callbacks.

Of course in both handlers (success and error) we are creating a closure over hugeData which is directly referenced from callback handlers.

My question is: since the result of AJAX call can be only either success or failure, will reusing of this code cause the memory leak over time? I would answer "yes", but I couldn't reliably prove this one in my local tests.

I'd like some more experienced guru to explain this one for me. I'd love response from anyone working with Angular on daily basis, but any jquery responses are welcome as well.

like image 611
ŁukaszBachman Avatar asked Jun 04 '13 11:06

ŁukaszBachman


People also ask

What are memory leaks example?

An example of memory leakThe memory leak would occur if the floor number requested is the same floor that the elevator is on; the condition for releasing the memory would be skipped. Each time this case occurs, more memory is leaked. Cases like this would not usually have any immediate effects.

How do I find a memory leak?

To find a memory leak, look at how much RAM the system is using. The Resource Monitor in Windows can be used to accomplish this. In Windows 8.1 and Windows 10: To open the Run dialogue, press Windows+R, then type "resmon" and click OK.

What are memory leaks?

DEFINITION A memory leak is the gradual deterioration of system performance that occurs over time as the result of the fragmentation of a computer's RAM due to poorly designed or programmed applications that fail to free up memory segments when they are no longer needed.


1 Answers

You will have a memory leak as soon as you return the result of $http() call (or whatever object or function that has access to hugeData) into the outer scope of fetchResults.

With your code, nothing big is exposed directly outside of fetchResults, and the result of $http() call will live until it either succeeds or fail, then calling the corresponding callback, finally getting GC'ed.

See for insights: http://jibbering.com/faq/notes/closures/#clIdRes

As @ŁukaszBachman observes, this does not guarantee that there are no memory leaks. Any dangling reference to your big object or to your callback with big object in scope, will cause woe.

So, let's check into $q implementation ($http is based on $q).

If you check https://github.com/angular/angular.js/blob/master/src/ng/q.js#L191, you can see that the resolve() method of the deferred first copies the list of registered callbacks in a variable local to the method:

var callbacks = pending;

subsequently nullifies the external pending (that was defined at the defer level)

pending = undefined;

then, at next tick, executes the callbacks. Things may get complicated by the fact that the callback's argument may be a deferred itself (adding a further delay to execution), but at most you could get into an infinite loop. (And that's not funny!). If you are lucky enough not to get into the loop, then at some point the callback array is exhausted, and then there is no reference whatsoever to the callback list, so it's available for GC.

But.

Things may go wrong if you force them to.

You may use arguments.callee inside a callback.

You can throw beer on your keyboard too.

If you jump out of the window, unless you live on the first floor, you will probably get hurt.

Happy EcmaScripting!

like image 164
rewritten Avatar answered Oct 31 '22 01:10

rewritten