Opened 10 years ago

Closed 5 years ago

#9958 closed enhancement (wontfix)

replaceChild optimization to have better IE performances

Reported by: vincentastek Owned by: bill
Priority: low Milestone: 2.0
Component: Dijit Version: 1.3.1
Keywords: Cc:
Blocked By: Blocking:

Description (last modified by bill)

Hi,

We're using Dojo here on quite loaded rich HTML interfaces. On a page we have 14 various dojo fields, 3 tabbed panes and some title panes.

We have very poor performances on IE6 (9 seconds to parse), and quite bad performances on IE8 (5 seconds to parse), so I had to find a workaround so we can let users use the application.

I ended by finding that half of the parsing time was spent in the IE function replaceChild used in _Widget.create() method. This function is very low to respond, especially on dojo widgets containers (using ContentPane?). I assume this is because it's the step where basic server generated node is replaced by complex dojo node, and IE has to refresh the display to take it into account.

As I've already been the witness of a bad IE display behaviour, I knew that IE usually refresh display only after a javascript function is ended, so I've grouped all the replacements at the end of the page and performances are significantly better (especially with containers which have complex contents). Parsing times are quite half smaller on IE6 and IE8.

I ended implementing this in the _Widget.js. I added an attribute name groupReplacement, default false value. In the create method, line 393, I replaced :

if(source && source.parentNode){        
    source.parentNode.replaceChild(this.domNode, source);
}

by

if(source && source.parentNode){
  if(this.groupReplacement){
    _wWidgetsNodes[_wWidgetsNodes.length] =  this.domNode;                                  _wWidgetsSourceNodes[_wWidgetsSourceNodes.length] = source;
  } else {      
    source.parentNode.replaceChild(this.domNode, source);
  }
}

I also replaced :

if(this.srcNodeRef && !this.srcNodeRef.parentNode){
  delete this.srcNodeRef;
}

by

if(!this.groupRendering){
  if(this.srcNodeRef && !this.srcNodeRef.parentNode){
    delete this.srcNodeRef;
  }
}

And at the end of my page, I call a js function that processes my arrays to do the replacements and the delete if needed, for all items. So I can configure all my widgets individually to work this way. As far as I tested, only Button linked to a menu doesn't allow this because a dom search is done when their mutual reference is processed. So all my widgets aside menus work like this now and IE works a lot better, and FFX 3.5 seems like performance are very little better too.

Can something like this be thought and implemented (more properly for sure) in all widgets, to allow IE to work better with complex dojo pages ?

Thanks,

Vincent

Change History (7)

comment:1 Changed 10 years ago by bill

Description: modified (diff)

Interesting. I don't understand why this would change the performance. You are still doing the same number of replaceChild() calls, aren't you? Just at a different time?

comment:2 Changed 10 years ago by liucougar

one possibility: by doing replaceChild in a tight loop, IE won't update the UI until the loop finishes. while if the replaceChild is called in different places, IE redraws more frequently

comment:3 Changed 10 years ago by liucougar

i think a better way of handling this is to use a "welcome screen" (like in themeTester.html) so most of the content is not visible until the UI is fully initialized

comment:4 Changed 10 years ago by bill

Milestone: tbdfuture

A welcome screen is a good idea too, but it's still worth considering a change that makes pages load twice as fast. Though seems like a big destabilizing change.

In theory no widgets should be depending on being attached to the DOM until startup() is called, but in reality probably some widgets are depending on that in postCreate(). Even some of the form widgets have setTimeout(resize, 0) type calls in them.

comment:5 Changed 9 years ago by bill

Milestone: future2.0
Owner: set to bill

comment:6 Changed 7 years ago by bill

Priority: highlow

comment:7 Changed 5 years ago by bill

Resolution: wontfix
Status: newclosed

This ticket doesn't really apply anymore in https://github.com/ibm-js/delite (which replaces dijit), because the top level node is no longer swapped out. (This is a basic principle of how Custom Elements work.) It's true though that as each widget initializes, it adds sub-nodes to the original top level node. Not sure how that affects performance. But anyway, that's enough of a different ball of wax to close this ticket for now.

Note: See TracTickets for help on using tickets.