Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Tree Performance

  1. #1

    Default Tree Performance

    I am investigating the use of the Tree control for the rather large data set that we have. Many nodes will have less than 10 or so children, but there are several that may contain hundreds. I wrote a simple "RandomTreeLoader" to generate 300 child nodes per level and used FireBug to profile the results.

    After looking at the profiles, the lion's share of the time is in "removeClass" that gets called 1805 times for 300 nodes. It is usually over 50% of the time spent. insertHtml usually comes in second, with render, addClass, and updateExpandIcon up there, too.

    I am going to continue digging at this code to see if I can figure out what's going on, but in the mean time, does anyone know why removeClass is being called 1805 times? InsertHtml is being called once per node and perhaps there is a way to do a bulk insert of all the nodes...?

    Any other ideas on how to optimize the tree?

    Thanks,
    David


    Here's the FireBug output:
    Code:
    removeClass	1805	49.5%	5406.25ms	5406.25ms	2.995ms	0ms	3718.75ms	ext-all-debug.js (line 2244)
    insertHtml	300	13.3%	1453.125ms	4437.5ms	14.792ms	0ms	46.875ms	ext-all-debug.js (line 191)
    addClass	903	6.44%	703.125ms	781.25ms	0.865ms	0ms	31.25ms	ext-all-debug.js (line 2218)
    render	300	5.15%	562.5ms	9421.875ms	31.406ms	15.625ms	1375ms	ext-all-debug.js (line 16887)
    updateExpandIcon	902	4.29%	468.75ms	6812.5ms	7.553ms	0ms	3718.75ms	ext-all-debug.js (line 16959)
    id	2400	3.29%	359.375ms	421.875ms	0.176ms	0ms	15.625ms	Ext.js (line 104)
    CustomEvent	2100	2.72%	296.875ms	453.125ms	0.216ms	0ms	15.625ms	yui-utilities.js (line 12)
    on	2100	2.15%	234.375ms	687.5ms	0.327ms	0ms	15.625ms	yui-bridge.js (line 156)
    listen	2100	1.86%	203.125ms	1296.875ms	0.618ms	0ms	15.625ms	ext-all-debug.js (line 1467)
    addListener	2100	1.29%	140.625ms	1437.5ms	0.685ms	0ms	31.25ms	ext-all-debug.js (line 1552)
    CustomEvent	2100	1.14%	125ms	125ms	0.06ms	0ms	15.625ms	yui-utilities.js (line 12)
    And here's my test code:
    Code:
    <html>
    	<head>
    		<meta http-equiv="Content-type" content="text/html; charset=utf-8"></meta>
    		<title>test</title>
    		<script src="ext/yui-utilities.js" type="text/javascript" charset="utf-8"></script>
    		
    		<script src="ext/source/core/Ext.js" type="text/javascript" charset="utf-8"></script>
    		<script src="ext/source/experimental/yui-bridge.js" type="text/javascript" charset="utf-8"></script>
    		<script src="ext/ext-all-debug.js" type="text/javascript" charset="utf-8"></script>
    		<script type="text/javascript" charset="utf-8">
    			Ext.tree.RandomTreeLoader = function(config){
    				this.loaded = false;
    			    this.loading = false;
    			    Ext.tree.RandomTreeLoader.superclass.constructor.apply(this, arguments);
    			    this.events["beforeload"] = true;
    			    this.events["load"] = true;
    			}
    			
    			Ext.extend(Ext.tree.RandomTreeLoader, Ext.tree.TreeLoader, {
    			    clearOnLoad : true,
    			    load : function(node, callback){
    					this.finishLoad.defer(250, this, [node, callback], false);
    			    },
    
    			    finishLoad : function(node, callback){
    			    	var ranNum=300;//Math.floor(Math.random()*300);
    					for (var i=0; i < ranNum; i++) {
    						var path = node.attributes.path + "-"+i;
    						node.appendChild(new Ext.tree.AsyncTreeNode({text: "Domain "+path, path: path, expanded: false, allowDrag: false, allowDrop: false}));
    					}
    
    					if(typeof callback == "function"){
                 		   callback(this, node);
                		}
    		    	}
    		    });
    
    			var TreeTest = function(){
        			// shorthand
        			var Tree = Ext.tree;
        
    			    return {
            			init : function(){
            				var viewEl = Ext.get('tree');
            				var tree = new Tree.TreePanel(viewEl, {
    			                animate:false,
    			                expanded: true,
    			                enableDD:false,
    			                containerScroll: true,
    			                loader: new Tree.RandomTreeLoader(),
    			                rootVisible:true
    			            });
    			            var root = new Tree.AsyncTreeNode({
    			                text: 'Domain 0',
    			                path: '0'
    			            });
    			            tree.setRootNode(root);
    			            
    			            tree.render();
        				}
    				}
    			}();
    			Ext.EventManager.onDocumentReady(TreeTest.init, TreeTest, true);
    		</script>
    		
    		<link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css" />
    	</head>
    	<body id="test">
    		<div id="tree">
    		</div>
    	</body>
    </html>

  2. #2
    Ext JS Premium Member
    Join Date
    Mar 2007
    Posts
    122

    Default

    I'm interested in this topic as well. We will have a tree with > 700 nodes - right now the YUI tree works great and loads very quickly (no performance stats on it yet). Hopefully when I convert to the Ext tree it's comparable or faster .

  3. #3
    Ext User rodiniz's Avatar
    Join Date
    Mar 2007
    Location
    Rio de Janeiro, Brazil
    Posts
    276

    Default

    Quote Originally Posted by kalebwalton
    I'm interested in this topic as well. We will have a tree with > 700 nodes - right now the YUI tree works great and loads very quickly (no performance stats on it yet). Hopefully when I convert to the Ext tree it's comparable or faster .
    Same problem here I was just using the tree today and firfox frose when I was trying to load 300 nodes.

  4. #4
    Sencha User Animal's Avatar
    Join Date
    Mar 2007
    Location
    Bédoin/Nottingham
    Posts
    30,892

    Default

    removeClass and hasClass are both doing new Rexp(...) every call.

    Try this override:

    Code:
    Ext.apply(Ext.Element.prototype, {
        classReCache: {},
    
        removeClass : function(className){
            if(!className){
                return this;
            }
            if(className instanceof Array){
                for(var i = 0, len = className.length; i < len; i++) {
                	this.removeClass(className[i]);
                }
            }else{
                var re = this.classReCache[className];
                if (!re) {
                	re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
                	this.classReCache[className] = re;
                }
                var c = this.dom.className;
                if(re.test(c)){
                    this.dom.className = c.replace(re, " ");
                }
            }
            return this;
        },
        hasClass : function(className){
        	return (this.dom.className.split(/\s+/).indexOf(className) != -1);
        },
    });

  5. #5
    Sencha User Animal's Avatar
    Join Date
    Mar 2007
    Location
    Bédoin/Nottingham
    Posts
    30,892

    Default

    leathekd, what do you make of that regex cacheing removeClass?

    I've has Firebug profiles telling me it's 10 times faster than the standard Ext one. hock:

  6. #6
    Sencha User tolstoj's Avatar
    Join Date
    Mar 2007
    Posts
    55

    Default

    Hi
    Thought I'd throw in the removeClass that Animal provided. After removing a surplus , (comma) at the end it compiled fine. Sure enough my page loaded fast but my grid and header toolbar was gone.

    Haven't investigated further, just my 2 cents

    Cheers
    Thomas

  7. #7

    Default

    Quote Originally Posted by Animal
    leathekd, what do you make of that regex cacheing removeClass?

    I've has Firebug profiles telling me it's 10 times faster than the standard Ext one. hock:
    I'm going to give it a try back on my work. I'm looking forward to the results.

    I'll let you know.

  8. #8
    Sencha User Animal's Avatar
    Join Date
    Mar 2007
    Location
    Bédoin/Nottingham
    Posts
    30,892

    Default

    Quote Originally Posted by tolstoj
    Hi
    Thought I'd throw in the removeClass that Animal provided. After removing a surplus , (comma) at the end it compiled fine. Sure enough my page loaded fast but my grid and header toolbar was gone.

    Haven't investigated further, just my 2 cents

    Cheers
    Thomas
    Hmm. Probably indicates that one or other of my methods doesn't work exactly as the original did. I'll put the override into my app and have a look sometime...

  9. #9

    Default

    Nice. Still ends up being 7 seconds, but that fix took removeClass from 5.5 seconds to 93 milliseconds. Not bad at all! Thanks for your help.

    Code:
    insertHtml	300	24.03%	1640.611ms	4609.338ms	15.364ms	0ms	93.749ms	ext-all-debug.js (line 191)
    render	300	12.36%	843.744ms	8906.194ms	29.687ms	15.624ms	109.374ms	ext-all-debug.js (line 16887)
    updateExpandIcon	902	11.21%	765.62ms	1796.864ms	1.992ms	0ms	31.25ms	ext-all-debug.js (line 16959)
    addClass	903	10.98%	749.996ms	906.246ms	1.004ms	0ms	31.25ms	ext-all-debug.js (line 2218)
    listen	2100	6.41%	437.499ms	1624.996ms	0.774ms	0ms	62.5ms	ext-all-debug.js (line 1467)
    id	2400	5.26%	359.374ms	406.249ms	0.169ms	0ms	15.625ms	Ext.js (line 104)
    CustomEvent	2100	4.35%	296.875ms	499.999ms	0.238ms	0ms	31.25ms	yui-utilities.js (line 12)
    on	2100	4.35%	296.874ms	796.873ms	0.379ms	0ms	31.25ms	yui-bridge.js (line 156)
    addListener	2100	4.12%	281.249ms	1906.245ms	0.908ms	0ms	62.5ms	ext-all-debug.js (line 1552)
    CustomEvent	2100	2.29%	156.25ms	156.25ms	0.074ms	0ms	15.625ms	yui-utilities.js (line 12)
    hasClass	903	2.29%	156.25ms	156.25ms	0.173ms	0ms	15.625ms	test.html (line 35)
    fireEvent	605	2.29%	156.249ms	171.874ms	0.284ms	0ms	62.5ms	ext-all-debug.js (line 10108)
    removeClass	1805	1.37%	93.748ms	93.748ms	0.052ms	0ms	15.625ms	test.html (line 14)
    Node	300	1.14%	78.125ms	93.75ms	0.313ms	0ms	15.625ms	ext-all-debug.js (line 10056)
    initEvents	300	0.92%	62.5ms	2015.62ms	6.719ms	0ms	78.125ms	ext-all-debug.js (line 16686)
    TreeNode	300	0.92%	62.499ms	203.123ms	0.677ms	0ms	15.625ms	ext-all-debug.js (line 16186)

  10. #10
    Sencha User jack.slocum's Avatar
    Join Date
    Mar 2007
    Location
    New York, NY
    Posts
    6,956

    Default

    I like caching the RE, this is something I do in other spots so I will add it in.

    The hasClass you have will be slower than the new hasClass in Element which uses String.indexOf with some space padding. Take a look at that one in SVN Nige.
    Jack Slocum
    Sencha Co-Founder, Ext JS Founder
    Original author of Ext JS 1, 2 & 3.
    Twitter: @jackslocum

Page 1 of 2 12 LastLast

Similar Threads

  1. Grid performance profile using Firebug
    By Animal in forum Ext 2.x: Help & Discussion
    Replies: 15
    Last Post: 27 Apr 2007, 10:30 AM
  2. Performance A2Rev5: Tab Switching with a tab being a Grid
    By Domitian in forum Ext 2.x: Help & Discussion
    Replies: 11
    Last Post: 8 Mar 2007, 7:52 AM
  3. Grid & Slow performance?
    By [email protected] in forum Ext 1.x: Bugs
    Replies: 2
    Last Post: 24 Oct 2006, 9:35 AM
  4. grid addRows performance
    By ericwaldheim in forum Ext 1.x: Help & Discussion
    Replies: 4
    Last Post: 19 Oct 2006, 10:40 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
  •