AngularJS and Memory Leaks

AngularJS is a great front-end framework, and I love it, but it appears that a lot of people are complaining about memory leaks. I spent last 2 days trying to isolate the cause of my memory leak too, but it turns out that mine was rather Heisenbergian, that is, the act of observing caused the problem! Before you start looking into memory leaks in AngularJS, you should make sure that you do two things:

1. Comment out all of your console.log() functions in your source. The log function apparently retains a reference to the variable that it outputted. So, if you do something like console.log(data), that "data" would never get garbage-collected, and your memory usage will keep on increasing (the hallmark of memory leak). Voila! You just created a memory leak by trying to observe it.

2. Turn off (disable) AngularJS Batarang (the developer plugin for Chrome). The same logic here. If you keep that on, your memory will not get garbage-collected.

After doing these two things, if you still see the memory usage keep climbing, you have a real memory leak (congrats).

Another thing to keep in mind: Chrome is a bit slow in garbage collecting. So, even if you have no memory leak, your memory usage on the Timeline page of Developer Tools may keep on increasing. Give it a little time. Or, click on the trash button at the bottom of the window (forces garbage collection).

If you don't see memory usage increase, but you see the node count in Chrome Developer Tools keep climbing, apparently that is not something you need to worry about.

The most likely culprit of memory leak in Angular is JQuery used in your directives. If you attach an event-listener in your directive using a JQuery plugin, the latter would keep a reference to your DOM even after Angular deletes its own reference to the DOM, which means it would never be garbage-collected by the browser, which in turn means "Detached DOM tree" in your memory  (You can see it in the "Profiles" page of Chrome Developer Tools. Take a snapshot, and search for "detached".). As you navigate around your app (loading different views/controllers), you will end up creating more of these detached DOMs.

Launch your app, take a snapshot of your memory in Developer Tools, and navigate around for a bit, and take another snapshot. You would probably see the number of detached DOMs increase. Even if the numbers remain the same, the "retained size" might keep increasing for each. This is because the same exact DOMs are repeatedly being created in memory without garbage-collection. By going down the tree browser, you can see what these DOMs are. And, then take a look at your directives to see if there are any event-listeners attached to them. Each JQuery plugin should offer a way to "destroy" itself. Listen for Angular's $destory event, and unbind the event-listener.