Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

ng-if memory leak #11618

Closed
astalker opened this issue Apr 16, 2015 · 10 comments
Closed

ng-if memory leak #11618

astalker opened this issue Apr 16, 2015 · 10 comments

Comments

@astalker
Copy link

I've noticed a possible memory leak with the ng-if directive. It appears to be failing to garbage collect HTML Elements.

I've set up two fiddles to compare ng-if with ng-show (which doesn't have the same issue).

ng-show - http://jsfiddle.net/neridum/8vo7ae8L/
ng-if - http://jsfiddle.net/neridum/hptt8wmu/

I simulated this by running a Heap Allocation profile and clicking between the views a few times (Incognito in Chrome Canary). With ng-if there is a left over HTMLDivElement that looks to be detached.

This doesn't appear to be for a specific version and is apparent with 1.2.1, 1.3.9 and 1.3.15.

I found a Stackoverflow post suggesting to run a cleanup method but I'm not sure that this is a suitable approach - http://stackoverflow.com/questions/26022481/ng-if-causing-memory-leak-in-angular-js

A related issue to this is #9748

@petebacondarwin
Copy link
Contributor

@astalker:
Does this occur on 1.4.x?
Does it occur on all browsers?

@carlosaugustoribeiro
Copy link

I have de same problem on Angular 1.4.1 and Chrome 40.0.2214

@petebacondarwin petebacondarwin added this to the 1.4.2 milestone Jul 2, 2015
@petebacondarwin
Copy link
Contributor

Right! We ought to get to the bottom of this...

@astalker
Copy link
Author

astalker commented Jul 2, 2015

I've rerun the tests on Chrome 43 with Angular 1.4.1 and ng-if will still create detached HTMLDivElements versus ng-show. I'm not really sure how to run the same type of tests in any other browser I'm afraid.

ng-show shows 4 HTMLDivElements after 6 and after 9 view changes.
ng-if shows 4 HTMLDivElements after 9 view changes 2 of which are detached. It shows 6 elements 2 of which are detached after 6 view changes.

In my tests, regardless of how many times I change the view it only seems to create 2 detached DivElements.

@lgalfaso
Copy link
Contributor

Was not able to reproduce the leak using Chrome 44.0.2403.155 on OS X

@Narretz Narretz modified the milestones: 1.4.5, 1.4.6 Aug 31, 2015
@petebacondarwin petebacondarwin modified the milestones: 1.4.6, 1.4.7 Sep 17, 2015
@petebacondarwin petebacondarwin modified the milestones: 1.4.7, 1.4.6 Sep 17, 2015
@Narretz Narretz modified the milestones: 1.4.7, 1.4.8 Oct 1, 2015
@alettieri
Copy link

I happen to stumble across this issue as well in angular v1.3.16.
Chrome 48.0.2552.0 canary (64-bit) Mac OSX

@vasiokos
Copy link

I also face this issue in a large scale application.Profiling with chrome developer tools produced a lot of DOM detached nodes.

@petebacondarwin
Copy link
Contributor

I have struggled with this today. I can see that there are a limited number of detached nodes but they do not seem to grow during normal usage. I think that they are related to the initial compile step of directives that make use of transclusion - i.e. the transcluded DOM is detached but is referenced in a closure that is referenced by long lived functions such as the ngIf watcher function.

@Narretz Narretz modified the milestones: 1.4.8, 1.4.9 Nov 26, 2015
@jbedard
Copy link
Contributor

jbedard commented Nov 29, 2015

I can't find any leaks in the example.

The detached nodes are the templates cloned by ng-if when the statement becomes true. This is how transclusion works for things like ng-if, ng-repeat, ng-view etc. where the transclusion may occur multiple times so the original element must be cloned and not used directly. If an ng-if wraps a large DOM this will result in a large detached DOM as the transclude template.

If you know your ng-if condition will never change you can use one-time binding which will allow the detached template nodes to be GCed.

652b83e may reduce the detached nodes in cases where it prevents templates from being inserted into the detached DOM. I think.

I do wonder if there are cases where these template nodes could get jQuery data on them. Because they are never cleaned properly with jQuery.cleanData...

@jbedard
Copy link
Contributor

jbedard commented Nov 29, 2015

Also note that ng-show is completely different then ng-if. All ng-show it does is toggle a class, where ng-if creates/destroys the nodes + scope each time based on a template. You really can't compare the two...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

9 participants