This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Regarding XSL performance on AIX


Hi Anand,

> In a similar fashion by calling nested templates, I transform the
> XSL to display the XML as a collapsible tree. When I do the
> transformation on WindowsNT it takes 20/25 seconds wheres on AIX it
> takes 3/4 minutes. I just can figure out why? Does any one have any
> idea why this happens? Please tell me how I can fine tune my XSL for
> enhanced performance.

The thing that's probably slowing your stylesheet down massively is
the fact that you've got a load of paths that are using the descendant
axis. You're also using absolute paths where I think you mean to use
relative paths, which I think means that your stylesheet will be
giving you unexpected results as well as being very slow.

If you do want to use absolute paths, e.g.:

  //NODE2

which collects all the NODE2 elements in the document, then you should
create global variables to hold the results of using them, rather than
calculating them afresh each time you encounter a NODE1 element.

If you want to collect information relative to a particular node, then
your path shouldn't start with a /. Take all the paths that you're
using in your NODE1 template:

   <!-- Check if this Node has Children -->
   <xsl:variable name = "countofNode2">
      <xsl:value-of select = "count(//NODE2)"/>
   </xsl:variable>

   <!-- Set the Variables like NodeAddress,levelidentifier,Nodename to be passed to
        javascript functions -->
   <xsl:variable name = "nodeaddr1">
        <xsl:value-of select = "(//NODE1/NODEADDRESS) "/>
   </xsl:variable>
   <xsl:variable name = "lidentifier1">
       <xsl:value-of select = "(//NODE1/LEVELIDENTIFIER) "/>
   </xsl:variable>
   <xsl:variable name = "nodename1">
      <xsl:value-of select = "(//NODE1/NODENAME) "/>
    </xsl:variable>
   
   <xsl:variable name = "color1">
      <xsl:value-of select = "(//NODE1/ISGREY) "/>
   </xsl:variable>

I think all these should be relative.

   <!-- Check if this Node has Children -->
   <xsl:variable name = "countofNode2">
      <xsl:value-of select = "count(NODE2)"/>
   </xsl:variable>

   <!-- Set the Variables like NodeAddress,levelidentifier,Nodename to be passed to
        javascript functions -->
   <xsl:variable name = "nodeaddr1">
        <xsl:value-of select = "NODEADDRESS"/>
   </xsl:variable>
   <xsl:variable name = "lidentifier1">
       <xsl:value-of select = "LEVELIDENTIFIER"/>
   </xsl:variable>
   <xsl:variable name = "nodename1">
      <xsl:value-of select = "NODENAME"/>
    </xsl:variable>
   
   <xsl:variable name = "color1">
      <xsl:value-of select = "ISGREY"/>
   </xsl:variable>

You should also be using the select attribute of xsl:variable, since
otherwise you get the processor to create result tree fragments, which
are relatively expensive to create compared to variables containing
pointers to nodes or values:

   <!-- Check if this Node has Children -->
   <xsl:variable name = "countofNode2" select="count(NODE2)" />

   <!-- Set the Variables like NodeAddress,levelidentifier,Nodename to be passed to
        javascript functions -->
   <xsl:variable name = "nodeaddr1" select="NODEADDRESS" />
   <xsl:variable name = "lidentifier1" select="LEVELIDENTIFIER" />
   <xsl:variable name = "nodename1" select="NODENAME" />
   <xsl:variable name = "color1" select="ISGREY" />

As a general rule, you should also try to use a step-by-step path down
to the nodes that you're interested in. So given that NODE2 elements
can only occur within a NODE1 element, which is the document element,
you should use:

  /NODE1/NODE2

This saves the processor a massive amount of work. Rather than having
to search through the entire document (including all the contents of
all those NODE4 elements), it can just look at the children of the
NODE1 element to try to find the NODE2 element that it's after.

You seem to be using the count of NODE2 elements as a way of testing
whether there are any NODE2 elements. That's a bad idea. You can tell
whether there are any NODE2 elements just by finding one NODE2
element. On the other hand, to count NODE2 elements, you have to go
all the way through the children of NODE1 to gather them all together.
So it will save you some time if you don't bother counting them, just
try seeing if there's one of them:

   <!-- Check if this Node has Children -->
   <xsl:variable name = "node2child" select="NODE2[1]" />

and then use xsl:choose rather than two xsl:ifs that cannot both be
true -- that means you only do the test once:

  <xsl:choose>
    <xsl:when test="$node2child">
      ... there are NODE2 children ...
    </xsl:when>
    <xsl:otherwise>
      ... there aren't NODE2 children ...
    </xsl:otherwise>
  </xsl:choose>

As Mike B.'s already pointed out, implementing loops using counters is
not going to be very efficient in XSLT. It's a much better idea to
apply templates to the NODE2 elements in order to process them, or use
xsl:for-each:

  <xsl:for-each select="NODE2">
    ... do stuff with the NODE2 elements ...
  </xsl:for-each>
  
Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]