Changeset 8685

Show
Ignore:
Timestamp:
05/21/07 23:41:22 (20 months ago)
Author:
alex
Message:

updates to improve the performance of _createNodesFromText. This checkins:

  • replaces the cloning logic w/ direct node removal
  • reuses the encapsulating node
  • moves regular expression calculations out of the fast path and moves string trimming to the caching logic (verified that it's not called outside of this code path)
  • hoists at least one invariant out of a loop (and this is regexp replacement, so it matters)
  • moves "appendChild" logic for putting nodes in the rendered DOM to after the replacement of the innerHTML of the container

On the "themeTest.html" page, these changes reduced the time to construct the ~90 widgets on that page by nearly 20ms (112ms->93ms, avg).

Refs #3092

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • dijit/trunk/base/TemplatedWidget.js

    r8647 r8685  
    209209        } 
    210210 
     211        templateString = templateString.replace(/^\s+|\s+$/g, ""); 
     212 
    211213        if(templateString.match(/\$\{([^\}]+)\}/g)){ 
    212214                // there are variables in the template so all we can do is cache the string 
     
    248250} 
    249251 
    250 dijit.base._createNodesFromText = function(/*String*/text){ 
    251         //      summary 
    252         //      Attempts to create a set of nodes based on the structure of the passed text. 
    253  
    254         text = text.replace(/^\s+|\s+$/g, ""); 
    255  
    256         var tn = dojo.doc.createElement("div"); 
    257         tn.style.visibility="hidden"; 
    258         dojo.body().appendChild(tn); 
    259         var tableType = "none"; 
     252(function(){ 
    260253        var tagMap = { 
    261254                cell: {re: /^<t[dh][\s\r\n>]/i, pre: "<table><tbody><tr>", post: "</tr></tbody></table>"}, 
     
    263256                section: {re: /^<(thead|tbody|tfoot)[\s\r\n>]/i, pre: "<table>", post: "</table>"} 
    264257        }; 
    265         for(var type in tagMap){ 
    266                 var map = tagMap[type]; 
    267                 if(map.re.test(text.replace(/^\s+/))){ //FIXME: replace with one arg?  is this a no-op? 
    268                         tableType = type; 
    269                         text = map.pre + text + map.post; 
    270                         break; 
    271                 } 
    272         } 
    273  
    274         tn.innerHTML = text; 
    275         if(tn.normalize){ 
    276                 tn.normalize(); 
    277         } 
    278  
    279         var tag = {cell: "tr", row: "tbody", section: "table"}[tableType]; 
    280         var parent = tn; 
    281         if(typeof tag != "undefined"){ 
    282                 parent = tn.getElementsByTagName(tag)[0]; 
    283         } 
    284  
    285         var nodes = []; 
    286         for(var x=0; x<parent.childNodes.length; x++){ 
    287                 nodes.push(parent.childNodes[x].cloneNode(true)); 
    288         } 
    289 //PORT  dojo.html.destroyNode(tn); FIXME: need code to prevent leaks and such 
    290         dojo.body().removeChild(tn); 
    291         return nodes;   //      Array 
    292 } 
     258 
     259        var tn; 
     260        var _parent; 
     261 
     262        dijit.base._createNodesFromText = function(/*String*/text){ 
     263                //      summary 
     264                //      Attempts to create a set of nodes based on the structure of the passed text. 
     265 
     266                if(!tn){ 
     267                        _parent = tn = dojo.doc.createElement("div"); 
     268                        tn.style.visibility="hidden"; 
     269                } 
     270                var tableType = "none"; 
     271                var rtext = text.replace(/^\s+/); 
     272                for(var type in tagMap){ 
     273                        var map = tagMap[type]; 
     274                        if(map.re.test(rtext)){ //FIXME: replace with one arg?  is this a no-op? 
     275                                tableType = type; 
     276                                text = map.pre + text + map.post; 
     277                                break; 
     278                        } 
     279                } 
     280 
     281                tn.innerHTML = text; 
     282                dojo.body().appendChild(tn); 
     283                if(tn.normalize){ 
     284                        tn.normalize(); 
     285                } 
     286 
     287                var tag = { cell: "tr", row: "tbody", section: "table" }[tableType]; 
     288                if(typeof tag != "undefined"){ 
     289                        _parent = tn.getElementsByTagName(tag)[0]; 
     290                } 
     291 
     292                var nodes = []; 
     293                /* 
     294                for(var x=0; x<_parent.childNodes.length; x++){ 
     295                        nodes.push(_parent.childNodes[x].cloneNode(true)); 
     296                } 
     297                */ 
     298                while(_parent.firstChild){ 
     299                        nodes.push(_parent.removeChild(_parent.firstChild)); 
     300                } 
     301                //PORT  dojo.html.destroyNode(tn); FIXME: need code to prevent leaks and such 
     302                _parent = dojo.body().removeChild(tn); 
     303                return nodes;   //      Array 
     304        } 
     305})(); 
    293306 
    294307// These arguments can be specified for widgets which are used in templates.