PDA

View Full Version : Finding source of memory leak



tm8747a
1 Apr 2015, 7:47 AM
I've searched for answers and haven't had much luck. My app appears to have what appears to be a memory leak in IE 11 (and probably lower versions too). Memory just keeps climbing and climbing and never goes back down. One thing I wanted to confirm, I thought that most memory leaks came from direct manipulation of the dom, where you forget to detach event handlers and such. But the section of my app where the leak happens has no direct dom manipulation whatsoever, it's all ExtJS components, which I thought cleaned up after themselves when they were destroyed. Essentially, I have a view that gets destroyed (via removeAll() call on container) and gets re-created. Doing this several consecutive times, you see the memory usage just increasing and memory is never reclaimed.

I just read the Sencha guide section on memory management, didn't find too many answers. Do I need to actually manually anything set on a view on destroy? Like, anything inside a view done with this.someObject = someObjectHere needs to be set to null on destroy? Even that has me somewhat confused, because it seems if that were the case, you could just add a function like this in a component:



onDestroy: function() {
this.callParent(arguments);

for (var key in this) {
this[key] = null;
}
}


But if it were so easy, they would have built it into the framework. Needless to say, I tried it and got an error, not sure why though, if the callParent() is running before what I'm doing, wouldn't there be no need for anything in this once it's done?

Any hint to point me in the right direction is appreciated.

skirtle
1 Apr 2015, 7:31 PM
First thing to confirm is that you aren't leaking components. Type this into your console:


Ext.ComponentManager.getCount();

If you keep creating/destroying a view and you see this count creeping up then you have components leaking. Floating components like menus are commonly leaked due to being hidden rather than destroyed when they're closed.

Usually JavaScript garbage collection (not to be confused with ExtJS destroy) will tidy up for you without the need for nulling out members during destruction. It is best practice to null-out significant objects during destruction but it isn't strictly required - it helps to ensure that any leaks only leak the parent object and not any of its children, it doesn't actually prevent a leak.

Much more important than nulling out members is calling the destroy method on any complex objects you create (usually via Ext.destroy or Ext.destroyMembers).

Pretty much anything can leak. Stores, AJAX requests, listeners (due to closures), ... In general you need to be careful to ensure anything you create gets destroyed.

Is your leak specific to IE? Chrome has some really good tools for finding leaks.

tm8747a
1 Apr 2015, 8:11 PM
Yes, the leak(s) seems to be only a problem in IE. So when you say destroy any significant object, how does that work if I have a combo where i defined the store using a simple object like { type: 'mystore', etc... } instead of actually manually instantiating an object? Do I need to actually do something like Ext.destroy(myCombo.getStore()) in the view's onDestroy function? This is the part that has me most confused, I don't quite see a clear indication anywhere of what I need to manually destroy and what i don't need to worry about.

skirtle
2 Apr 2015, 4:46 AM
If you're passing in a store config to a combobox you don't need to destroy that yourself. The combo knows it's been passed a config and assumes that the store is for its use only. If you passed in an instantiated store the combo wouldn't know for sure that it's the only component using that store so it wouldn't destroy it.

That said, just because a store isn't destroyed doesn't necessarily mean that it'll leak. So long as there are no references to it then it'l be garbage collected. The problem with stores is that references can easily sneak out. For example, all the records in a store have a reference to the store, so if any of the records exist outside the store (say they're bound to a form) then that single record will keep the entire store, including al of its records, from being garbage collected. Destroying the store will tear down all these internal links and ensure that only records that are still being used won't be garbage collected.

Setting an id on the store will also prevent it from being garbage collected because it registers it with the store manager. Again, destroying deals with unregistering.

If your leaks are in IE only then you're going to struggle as it suggests you aren't doing anything wrong when it comes to destroying ExtJS objects. I haven't used the IE 11 memory profiler but from the docs it looks like it has similar functionality to the Chrome equivalent:

https://msdn.microsoft.com/en-us/library/ie/dn255003%28v=vs.85%29.aspx

tm8747a
2 Apr 2015, 6:43 AM
Thanks for the detailed answer, makes a lot of sense. I'm going memory leak hunting now! Thanks again for taking the time, it's very appreciated.