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


Hello Jeni and Mike,
Thanks for your help and suggestions.I followed these and have manged to improve the performance of my Transformation on AIX a lot.( I have used relative paths instead of absolute ones,used xsl;choose and am traversing the XML tree displaying nodes as I encounter them.) Is it possible to still further fine tune my XSL?(The current one takes about 50 seconds on AIX when there are a large no. of nodes.)
My XML:
<?xml:stylesheet type="text/xsl" href="Hierarchy.xsl" version="1.0" encoding="UTF-8"?>

<!-- <?xml version="1.0" encoding="UTF-8"?> -->

<NODE1>
<NODEADDRESS>1</NODEADDRESS> 
<LEVELIDENTIFIER>1</LEVELIDENTIFIER> 
<NODENAME>STOP AND SHOP                      </NODENAME> 
<ISGREY>0</ISGREY> 
<NODE2> 
<NODEADDRESS>1:1</NODEADDRESS> 
<LEVELIDENTIFIER>2</LEVELIDENTIFIER> 
<NODENAME>GROCERY                            </NODENAME> 
<ISGREY>1</ISGREY> 
<NODE3> 
<NODEADDRESS>1:1:1</NODEADDRESS> 
<LEVELIDENTIFIER>3</LEVELIDENTIFIER> 
<NODENAME>GROCERY OTHER                      </NODENAME> 
<ISGREY>0</ISGREY> 
<NODE4> 
<NODEADDRESS>1:1:1:1</NODEADDRESS> 
<LEVELIDENTIFIER>5</LEVELIDENTIFIER> 
<NODENAME>GRATED CHEESE                      </NODENAME> 
<ISGREY>1</ISGREY> 
</NODE4> 


120 records of type Node 4

<NODE4> 
<NODEADDRESS>1:1:1:128</NODEADDRESS> 
<LEVELIDENTIFIER>5</LEVELIDENTIFIER> 
<NODENAME>IRISH FOODS                        </NODENAME> 
<ISGREY>0</ISGREY> 
</NODE4> 
</NODE3> 
</NODE2> 
<NODE2> 
<NODEADDRESS>1:2</NODEADDRESS> 
<LEVELIDENTIFIER>2</LEVELIDENTIFIER> 
<NODENAME>GENERAL MERCH                      </NODENAME> 
<ISGREY>1</ISGREY> 
</NODE2> 
<NODE2> 
<NODEADDRESS>1:3</NODEADDRESS> 
<LEVELIDENTIFIER>2</LEVELIDENTIFIER> 
<NODENAME>PRODUCE                            </NODENAME> 
<ISGREY>0</ISGREY> 
</NODE2> 
<NODE2> 
<NODEADDRESS>1:4</NODEADDRESS> 
<LEVELIDENTIFIER>2</LEVELIDENTIFIER> 
<NODENAME>MEAT                               </NODENAME> 
<ISGREY>1</ISGREY> 
</NODE2> 
<NODE2> 
<NODEADDRESS>1:5</NODEADDRESS> 
<LEVELIDENTIFIER>2</LEVELIDENTIFIER> 
<NODENAME>FROZEN                             </NODENAME> 
<ISGREY>0</ISGREY> 
</NODE2> 
<NODE2> 
<NODEADDRESS>1:6</NODEADDRESS> 
<LEVELIDENTIFIER>2</LEVELIDENTIFIER> 
<NODENAME>FLORIST                            </NODENAME> 
<ISGREY>1</ISGREY> 
</NODE2> 
<NODE2> 
<NODEADDRESS>1:7</NODEADDRESS> 
<LEVELIDENTIFIER>2</LEVELIDENTIFIER> 
<NODENAME>DAIRY                              </NODENAME> 
<ISGREY>0</ISGREY> 
</NODE2> 
<NODE2> 
<NODEADDRESS>1:8</NODEADDRESS> 
<LEVELIDENTIFIER>2</LEVELIDENTIFIER> 
<NODENAME>HBC                                </NODENAME> 
<ISGREY>1</ISGREY> 
</NODE2> 
</NODE1>

My XSL now looks as given below:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version = "1.0">
<xsl:output method="html"/>

<xsl:template match="/"> <!-- match for the Root Element of the XML Document -->
   <xsl:apply-templates /> 
</xsl:template>

<xsl:template match="NODE1">

   <!-- 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) "/>

   <!-- Display "NODE1" tag -->
   <table>
   <xsl:choose>
   <xsl:when test="($color1 &gt; 0)">
   <TR class="DARK">
     	  <TD>
       	  
	  <!-- Display Anchor Image Link -->
	  <xsl:choose>
	  <xsl:when test="($countofNode2 &gt; 0)">
            <A class="hier" href="javascript:collapse('{$nodeaddr1}','{$lidentifier1}','{$nodename1}');">
              <img src="\pricing\images\treePics\downarrow.gif" border="0" />
            </A>
	  </xsl:when>
	  <xsl:otherwise>
            <A class="hier" href="javascript:expand('{$nodeaddr1}','{$lidentifier1}','{$nodename1}');">
              <img src="\pricing\images\treePics\rightarrow.gif" border="0" />
            </A>
	  </xsl:otherwise>
	  </xsl:choose>
          <!-- Display Anchor Text Link -->
           <A class="hier" href="javascript:selectNode('{$nodeaddr1}','{$lidentifier1}','{$nodename1}');"> 
                 <xsl:value-of select="NODENAME"/>
              </A>
          </TD>
      </TR>
    </xsl:when>
     <xsl:otherwise>
     <TR class="WHITE">
     	  <TD>
       	  
	  <!-- Display Anchor Image Link -->
	  <xsl:choose>
	  <xsl:when test="($countofNode2 &gt; 0)">
            <A class="hier" href="javascript:collapse('{$nodeaddr1}','{$lidentifier1}','{$nodename1}');">
              <img src="\pricing\images\treePics\downarrow.gif" border="0" />
            </A>
	  </xsl:when>
	  <xsl:otherwise>
            <A class="hier" href="javascript:expand('{$nodeaddr1}','{$lidentifier1}','{$nodename1}');">
              <img src="\pricing\images\treePics\rightarrow.gif" border="0" />
            </A>
	  </xsl:otherwise>
	  </xsl:choose>
	  <!-- Display Anchor Text Link -->
           <A class="hier" href="javascript:selectNode('{$nodeaddr1}','{$lidentifier1}','{$nodename1}');"> 
                 <xsl:value-of select="NODENAME"/>
              </A>
          </TD>
      </TR>
    </xsl:otherwise>
    </xsl:choose>
  </table>
<xsl:variable name="j" select="1"> </xsl:variable>
<xsl:variable name = "count1" select = "count(NODE2)"/>

   <xsl:call-template name = "forloop1" >
      <xsl:with-param name = "j" select = "$j"/>
      <xsl:with-param name = "count1" select = "$count1"/>
   </xsl:call-template>


</xsl:template>

<!-- Anand Forloop1-->
<xsl:template name= "forloop1">
   <xsl:param name = "j"/>
   <xsl:param name = "count1"/>
   
   <!-- Check if this Node has Children -->
   
   <xsl:variable name="i" select="1"> </xsl:variable>
   <xsl:variable name = "count2" select = "count(NODE2[$j]/NODE3) "/>
 
   <xsl:variable name = "nodeaddr2" select = "(NODE2[$j]/NODEADDRESS) "/>
    <xsl:variable name = "lidentifier2" select = "(NODE2[$j]/LEVELIDENTIFIER) "/>
    <xsl:variable name = "nodename2" select = "(NODE2[$j]/NODENAME) "/>
    <xsl:variable name = "color2" select = "(NODE2[$j]/ISGREY) "/>
    
 <!-- For "Node2" tag -->
   <xsl:if test="($count1 &gt; 0)">
    <xsl:choose>
    <xsl:when test="($color2 &gt; 0)">
     <TR class="DARK">
       	  <TD>&#160;&#160;
       	  <!-- Display Anchor Image Link -->
       	  <xsl:choose>
	  <xsl:when test="($count2 &gt; 0)"> 
            <A class="hier" href="javascript:collapse('{$nodeaddr2}','{$lidentifier2}','{$nodename2}');">
              <img src="\pricing\images\treePics\downarrow.gif" border="0" />
            </A>
	  </xsl:when>
	  <xsl:otherwise>
            <A class="hier" href="javascript:expand('{$nodeaddr2}','{$lidentifier2}','{$nodename2}');">
              <img src="\pricing\images\treePics\rightarrow.gif" border="0" />
            </A>
	  </xsl:otherwise>
	  </xsl:choose>
          <!-- Display Anchor Text Link -->
           <A class="hier" href="javascript:selectNode('{$nodeaddr2}','{$lidentifier2}','{$nodename2}');"> 
                <xsl:value-of select="NODE2[$j]/NODENAME"/>
              </A>
          </TD>
     </TR> 
   </xsl:when>
   <xsl:otherwise>
    <TR class="WHITE">
      	  <TD>&#160;&#160;
       	  <!-- Display Anchor Image Link -->
	  <xsl:if test="($count2 &gt; 0)">
            <A class="hier" href="javascript:collapse('{$nodeaddr2}','{$lidentifier2}','{$nodename2}');">
              <img src="\pricing\images\treePics\downarrow.gif" border="0" />
            </A>
	  </xsl:if>
	  <xsl:if test="not($count2 &gt; 0)">
            <A class="hier" href="javascript:expand('{$nodeaddr2}','{$lidentifier2}','{$nodename2}');">
              <img src="\pricing\images\treePics\rightarrow.gif" border="0" />
            </A>
	  </xsl:if>
          <!-- Display Anchor Text Link -->
           <A class="hier" href="javascript:selectNode('{$nodeaddr2}','{$lidentifier2}','{$nodename2}');"> 
                <xsl:value-of select="NODE2[$j]/NODENAME"/>
              </A>
          </TD>
     </TR> 
     </xsl:otherwise>
     </xsl:choose>
   </xsl:if>

  <xsl:call-template name = "forloop2" >
      <xsl:with-param name="i" select="$i" />
      <xsl:with-param name="j" select="$j" />
      <xsl:with-param name="count2" select="$count2" />
      <xsl:with-param name="count1" select="$count1" />
 </xsl:call-template>


   <xsl:if test="$j &lt; $count1">
      <xsl:call-template name="forloop1">
         <xsl:with-param name="j" select="$j+1"/>
         <xsl:with-param name="count1" select="$count1"/>
      </xsl:call-template>
   </xsl:if>
</xsl:template>

<!-- Anand Forloop2-->
<xsl:template name = "forloop2" >
   <xsl:param name="i" />
   <xsl:param name="j" />
   <xsl:param name = "count2" />
   <xsl:param name = "count1"/>
   
   <!-- Check if this Node has Children -->
   
   <xsl:variable name = "nodeaddr3" select = "(NODE2[$j]/NODE3[$i]/NODEADDRESS) "/>
   <xsl:variable name = "lidentifier3" select = "(NODE2[$j]/NODE3[$i]/LEVELIDENTIFIER) "/>
   <xsl:variable name = "nodename3" select = "(NODE2[$j]/NODE3[$i]/NODENAME) "/>
   <xsl:variable name = "color3" select = "(NODE2[$j]/NODE3[$i]/ISGREY) "/>
   <xsl:variable name="h" select="1"> </xsl:variable>
   <xsl:variable name = "count3" select = "count(NODE2[$j]/NODE3[$i]/NODE4)"/>
 
   <!-- For "NODE3" tag -->
   <xsl:if test="($count1 &gt; 0)">
      <xsl:if test="($count2 &gt; 0)">
         <xsl:choose>
         <xsl:when test="($color3 &gt; 0)">
           <TR class="DARK">
       
       	  <TD>&#160;&#160;&#160;&#160;
	  <!-- Display Anchor Image Link -->
	  <xsl:if test="($count3 &gt; 0)">
            <A class="hier" href="javascript:collapse('{$nodeaddr3}','{$lidentifier3}','{$nodename3}');">
              <img src="\pricing\images\treePics\downarrow.gif" border="0" />
            </A>
	  </xsl:if>
	  <xsl:if test="not($count3 &gt; 0)">
            <A class="hier" href="javascript:expand('{$nodeaddr3}','{$lidentifier3}','{$nodename3}');">
              <img src="\pricing\images\treePics\rightarrow.gif" border="0" />
            </A>
	  </xsl:if>
          <!-- Display Anchor Text Link -->
           <A class="hier" href="javascript:selectNode('{$nodeaddr3}','{$lidentifier3}','{$nodename3}');"> 
                 <xsl:value-of select="NODE2[$j]/NODE3[$i]/NODENAME"/>
              </A>
          </TD>
     </TR> 
     </xsl:when>
     <xsl:otherwise>
     <TR class="WHITE">
       	  <TD>&#160;&#160;&#160;&#160;
	  <!-- Display Anchor Image Link -->
	  <xsl:choose>
	  <xsl:when test="($count3 &gt; 0)">
            <A class="hier" href="javascript:collapse('{$nodeaddr3}','{$lidentifier3}','{$nodename3}');">
              <img src="\pricing\images\treePics\downarrow.gif" border="0" />
            </A>
	  </xsl:when>
	  <xsl:otherwise>
            <A class="hier" href="javascript:expand('{$nodeaddr3}','{$lidentifier3}','{$nodename3}');">
              <img src="\pricing\images\treePics\rightarrow.gif" border="0" />
            </A>
	  </xsl:otherwise>
	  </xsl:choose>
          <!-- Display Anchor Text Link -->
           <A class="hier" href="javascript:selectNode('{$nodeaddr3}','{$lidentifier3}','{$nodename3}');"> 
                 <xsl:value-of select="NODE2[$j]/NODE3[$i]/NODENAME"/>
              </A>
          </TD>
     </TR> 
     </xsl:otherwise>
     </xsl:choose>
      </xsl:if>
   </xsl:if>

Thanks and Regards,
Anand

>>> Jeni Tennison <jeni@jenitennison.com> 05/17/02 02:51PM >>>
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 NODE2element. 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 


 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]