Page 2 of 2 FirstFirst 12
Results 11 to 15 of 15

Thread: Blog post: Tips for finding memory leaks in Sencha applications

  1. #11
    Sencha - Ext JS Dev Team nohuhu's Avatar
    Join Date
    Jun 2011
    Location
    Redwood coast
    Posts
    401

    Default

    Great post Mats, very detailed. I planned to get down with writing detailed instructions on how to hunt for memory leaks but you beat me to it. :)

    When looking at the retained tree, I find it most useful to filter the view to only include "constructor" objects and then sorting by distance descending. I usually look for very long retain paths, say longer than 12 links should be suspicious.

    Another trick you might want to add is taking a heap snapshot before running test case and another after that, and comparing snapshots.

    Good luck with plugging Touch leaks. ;) We've done massive amount of work for 6.0 but I doubt that it's been backported to Touch...
    Regards,
    Alex.

  2. #12
    Sencha - Ext JS Dev Team nohuhu's Avatar
    Join Date
    Jun 2011
    Location
    Redwood coast
    Posts
    401

    Default

    Quote Originally Posted by mitchellsimoens View Post
    I don't think it's that simple or else why nullify the items collection and other things? For example, in Ext.Component#destroy, there is this:

    Code:
                    me.data = me.el = me.frameBody = me.rendered = me.afterRenderEvents = null;
                    me.tpl = me.renderTpl = me.renderData = null;
                    me.focusableContainer = me.container = me.scrollable = null;
    me.data for example, then that's unneeded code or just for good measure in case the object/array is referenced somewhere else?
    It's very simple on one hand, not so simple on another. GC in JavaScript will collect any items that have no retaining path to the root object (window) so circular references are not a problem. Well, circular references that only involve JavaScript objects are not a problem. :)

    However the number of ways an Ext JS object instance can be retained all the way up to the root is nothing short of staggering. It is true that nulling out all references we can account for is not, strictly speaking, necessary for the object to be garbage collected. However it is a practical precaution for the case of the object being erroneously retained so that it wouldn't in turn retain a lot of other things. There's no question that objects are going to be retained when they shouldn't, we're just trying to minimize the damage.
    Regards,
    Alex.

  3. #13
    Sencha Premium Member
    Join Date
    Sep 2007
    Posts
    13,976

    Default

    All this code still leaks, because the instance of "mySomething" is never destroyed and so never removed from the ComponentManager. This also means all related elements are not destroyed and so not removed from the Element Cache.

    Quote Originally Posted by mitchellsimoens View Post
    Something like this is a memory leak also (which I see in code all the time, I use this method too):

    Code:
    Ext.define('MyClass', {
        extend : 'Ext.container.Container',
        xtype  : 'myclass',
    
        config : {
            mySomething : {
                xclass : 'MySomething'
            }
        },
    
        applyMySomething : function(something) {
            if (something && !something.isComponent) {
                something = Ext.create(something);
            }
    
            return something;
        }
    });
    Now when you create an instance and destroy it, the mySomething property still resolves to the instance created in the applyMySomething. So you have to take care of it:

    Code:
    Ext.define('MyClass2', {
        extend : 'Ext.container.Container',
        xtype  : 'myclass2',
    
        config : {
            mySomething : {
                xclass : 'Ext.Component'
            }
        },
        
        destroy : function() {
            this.setMySomething(null);
            
            this.callParent();
        },
    
        applyMySomething : function(something) {
            if (something && !something.isComponent) {
                something = Ext.create(something);
            }
    
            return something;
        }
    });
    Or, if you want to clear all items in the class' config object, use the configurator:

    Code:
    Ext.define('MyClass3', {
        extend : 'Ext.container.Container',
        xtype  : 'myclass3',
    
        config : {
            mySomething : {
                xclass : 'Ext.Component'
            }
        },
        
        destroy : function() {
            var configurator = this.getConfigurator(),
                configs      = configurator.configs,
                name;
            
            for (name in configs) {
                if (configs.hasOwnProperty(name)) {
                    configs[name].setter.call(this, null);
                }
            }
            
            this.callParent();
        },
    
        applyMySomething : function(something) {
            if (something && !something.isComponent) {
                something = Ext.create(something);
            }
    
            return something;
        }
    });



    To destroy it properly you can do something like this:
    Code:
    Ext.define('MyClass2', {    extend : 'Ext.container.Container',
        xtype  : 'myclass2',
    
    
        config : {
            mySomething : {
                xclass : 'Ext.Component'
            }
        },
        
        destroy : function() {
            this.setMySomething(null);
            
            this.callParent();
        },
    
    
        applyMySomething : function(something) {
            if (something && !something.isComponent) {
                something = Ext.create(something);
            }
    
    
            return something;
        },
        updateMySomething : function(something, oldSomething) {
            if (oldSomething && oldSomething.isComponent) {
                  Ext.destroy(oldSomething);
            }
           
        }
    });

  4. #14
    Sencha Premium User mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    40,379

    Default

    Quote Originally Posted by sven View Post
    All this code still leaks, because the instance of "mySomething" is never destroyed and so never removed from the ComponentManager. This also means all related elements are not destroyed and so not removed from the Element Cache.
    That is true, my example did not have the updater that usually will add the item to the items collection that I normally have. When added to the items collection, when the MyClass is destroyed, since mySomething would be added to the items it would be destroyed. This is something that in my head was understood but of course my example did not show. To which I've updated my post to include that bit.
    Mitchell Simoens @LikelyMitch

    Check out my GitHub:
    https://github.com/mitchellsimoens

    Posts are my own, not any current, past or future employer's.

  5. #15
    Sencha Premium User
    Join Date
    Nov 2010
    Location
    Chicago
    Posts
    2,339

Page 2 of 2 FirstFirst 12

Similar Threads

  1. Blog post on testing Sencha Touch applications
    By mankz in forum Sencha Touch 2.x: Examples and Showcases
    Replies: 0
    Last Post: 14 Feb 2013, 3:01 AM
  2. Blog post on Sencha Animator
    By infield in forum Sencha Animator Help & Discussion
    Replies: 2
    Last Post: 23 Jun 2011, 4:23 PM
  3. Debugging best practices for finding memory leaks and performance issues
    By brookd in forum Ext 3.x: Help & Discussion
    Replies: 0
    Last Post: 1 Jan 2010, 4:59 PM
  4. Off Topic: Finding Memory Leaks in IE?
    By cluettr in forum Ext 1.x: Help & Discussion
    Replies: 0
    Last Post: 22 Sep 2007, 10:28 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •