Skip to content

Commit

Permalink
fix(Scope): aggressively clean up scope on $destroy to minimize leaks
Browse files Browse the repository at this point in the history
Due to a known V8 memory leak[1] we need to perform extra cleanup to make it easier
for GC to collect this scope object.

The theory is that the V8 leaks are due to inline caches which are caches
built on the fly to speed up property access for javascript objects.

By cleaning the scope object and removing all properties, we clean up ICs
as well and so no leaks occur.

I was able to manually verify that this fixes the problem for the following
example app: http://plnkr.co/edit/FrSw6SCEVODk02Ljo8se?p=preview

Given the nature of the problem I'm not 100% sure that this will work around
the V8 problem in scenarios common for Angular apps, but I guess it's better
than nothing.

[1] V8 bug: https://code.google.com/p/v8/issues/detail?id=2073

Closes angular#6794
Closes angular#6856
  • Loading branch information
IgorMinar authored and troch committed Mar 30, 2014
1 parent ec8e395 commit f505bcf
Showing 1 changed file with 15 additions and 4 deletions.
19 changes: 15 additions & 4 deletions src/ng/rootScope.js
Original file line number Diff line number Diff line change
Expand Up @@ -731,15 +731,26 @@ function $RootScopeProvider(){

forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));

// sever all the references to parent scopes (after this cleanup, the current scope should
// not be retained by any of our references and should be eligible for garbage collection)
if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;

// 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;
// This is bogus code that works around V8's memory leak coming from ICs
// see: https://code.google.com/p/v8/issues/detail?id=2073#c26
//
// for more info also see:
// - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
// - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
for (var prop in this) {
if (hasOwnProperty.call(this, prop)) {
this[prop] = null;
}
}
// recreate the $$destroyed flag
this.$$destroyed = true;
},

/**
Expand Down

0 comments on commit f505bcf

Please sign in to comment.