26

So I have a pretty simple Angular Application and I am trying to figure out what is causing detached DOM trees to show up in the chrome profiler. So for example, when you load up this page:

http://rztest.nodejitsu.com/dashboard

I get 2 detached DOM trees, one with 2 entries and another with 3 entries. This page does not use any custom directives so it must be something with either Angular or jQuery however I just don't see anything that would cause these detached DOM trees.

The issue becomes even bigger (if you click on the projects link and do another profile, there are a lot more detached DOM trees and entries in them) so I am hoping if I can fix this very simple example, it will cascade throughout the rest of the application.

Also note that I am using ui-router however I have tried this same thing with Angular's default router with the same results. Even the todomvc Angular app (http://todomvc.com/architecture-examples/angularjs/#/) which does not use jQuery has detached DOM trees.

UPDATE

I have pulled jQuery out of the application and on my simple page, all but one detached dom tree goes away (and that one is from AngularJS which I know where it is). When I try it for a more complex page (with a custom directive that has a templateUrl and does transclusion), removing jQuery does not seem to help.

I am not sure if jQuery is the actually issue (or maybe part of it) or how Angular using jQuery/jqLite.

Does anyone know if there is a existing detached DOM tree known in jQuery 1.10.x?

ryanzec
  • 27,284
  • 38
  • 112
  • 169
  • I've had trouble debugging memory in Chrome a few times, do these DOM trees still get left here if you turn off JS optimisations when you start the browser? Use the command `chrome --js-flags="--nocrankshaft --noopt"`. I tried to find a sensible source for the flags, [Karma Chrome Launcher](https://github.com/karma-runner/karma-chrome-launcher/blob/master/index.js#L39) is the best I could find. – Andyrooger Oct 18 '13 at 00:51
  • Yes, they still show up – ryanzec Oct 18 '13 at 12:04
  • 3
    Is it possible that the detached dom nodes are essentially angular.element() instantiations attached to a private var created by a directive? Let's say you have a directive with a template. Angular is going to create an angular.element and inject that into the link function. That compiled template is cached to be re-used on the next link function execution. It would seem to me that there would be at least one detached dom node for most directives. Maybe you could include some more details to show exactly when you get this issue and which nodes you expect to be garbage collected. – Jason Aden Oct 21 '13 at 17:49
  • See if this info helps [Finding JS memory leak in chrome dev tools](http://stackoverflow.com/questions/11930050/finding-js-memory-leak-in-chrome-dev-tools) – Bob Tate Dec 11 '13 at 23:18

1 Answers1

4

I've spent a good few hours debugging DOM node leaks in a number of large AngularJS applications.

I find a lot of detached DOM elements aren't garbage collected as jQuery has a reference to them from some internal cache it keeps. I'm convinced there is some Angular / jQuery issue at play.

Unfortunately I've found digging into the issue quickly creates more questions than answers (For instance, I noticed that in my application opening / closing a view would result in detached DOM elements...but re-opening/closing wouldn't create any more) - In the end, I had to make a compromise:

When an element is destroyed, I would recursively remove that elements children from their parents.

I admit it is an absolute hack - But the upshot is that any leaking DOM elements will no longer hold onto large subtrees of elements and so the memory leak will become much less of an issue.

If you don't find a solution to this issue... this will certainly help keep the leak under some kind of control.

Richard Walton
  • 4,789
  • 3
  • 38
  • 49