I got a really strange memory leak going on in our application. We have 
rather big angular (1.1.4) based app, and we noticed huge memory leak.
We are using ui-router and every time we switch between big states (which 
have lots of JS and DOM in them) we leak about 5 MB of JavaScript memory, 
and big amounts of DOM as well.
After 10 transitions between states our app takes about 1 GB of memory on 
Chrome.

After rather painful investigation I came to the following conclusions for 
which I would really like to get a second opinion and possible some kind of 
explanation (because I can't wrap my head around it)

   1. This is not related to ui-router in any way
   2. A cause looks like the leak of $scope for the root state from which 
   we transition away.
   3. The leak is result of state root scope been alive after transition 
   which keeps alive all the methods and watch expressions on that scope which 
   in turn keep alive all the closures of those methods
      1. For controller this means that big chunks of that controller are 
      keept alive
      2. For directives it means that any references they have to DOM 
      elements are kept alive as they are in the closure of the watch 
expressions 
      applied by the directive.
      A really good example for this is ui-if / ng-if which has reference 
      to it's element which is kept alive, which in turn essentially keeps 
alive 
      the entire DOM for our state as we have the ui-if at the root of the 
state.
   4. Unclear why, but $scope leaks when there are methods on scope that 
   reference scope itself, 
   like 
   
   $scope.flipFlag = function(){ *$scope*.flag = !*$scope*.flag }
   
   If same code is written as 
   
   $scope.flipFlag = function(){ *this*.flag = !*this*.flag }
   
   Then it looks like scope does not leak.
   5. This issue reproduces both on angular 1.1.4 and on 1.2.5

I have been using Chrome DevTools heap dump (didn't find a good and easy 
way to get heap dump on other browsers, if there, please share) to detect 
this issue.

I have reproduction of this issue at 
http://plnkr.co/edit/JZbtZ13Ml1aDjNJug1gu?p=preview on top of angular 1.2.5
What we do in this reproduction is set nad unset ng-include to point to a 
template with a controller.
In the controller we have scope method that references $scope.

To see the leak, on reproduction page, after accessing it, take a heap dump 
and there on summary view filter by Child constructor.
You will see that there are two scopes leaking, with ids 004 and 005, where 
005 is the scope for the controller injected in the view.html and 004 is 
it's prototype.
>From what I can see 004 isn't released because it's held by 005 (as it's 
prototype).
And 005 isn't released, well here it's not so clear, from what I can see 
it's not released because it has a function that has it in it's closure / 
scope.

If the issue does not reproduce, play around with show and hide buttons a 
few times, make sure to hide as last step.

I'm not clear if this is an angular bug, or Chrome GC bug, any ideas and 
help will be much appreciated.

I do want to note that in angular.js in Scope.$destroy we have this

        // This is bogus code that works around Chrome's GC leak
        // see: 
https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
        this.$parent = this.$$nextSibling = this.$$prevSibling = 
this.$$childHead =
            this.$$childTail = null;

So may be we need to clear not only $parent and so on, but all the 
properties owner by scope ?
But that won't help as well in all cases as from what I can see we don't 
actually run Scope.$destroy on each scope, we only broadcast to child 
scopes.

Help


-- 
You received this message because you are subscribed to the Google Groups 
"AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to