XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

EXSLT for MSXML
by Dimitre Novatchev | Pages: 1, 2, 3

Is XSLT Inefficient?

Today the prevailing opinion is that XSLT applications are quite inefficient as compared to applications written in a conventional programming language. Therefore, it would be interesting to see how this XSLT-based implementation compares to other implementations of EXSLT.

It was of particular interest how different EXSLT implementations behave with very large inputs. One of the tests was performed with all functions of the Sets module over a node set of 10000 nodes. The second test ran these functions on a much shorter node set consisting of 2000 nodes. I tested the Sets implementations of the following eight XSLT processors: Xalan C 1.5 ( C ), Saxon 6.5.2 (Java), Msxml4 (XSLT), JD (Java), .Net (C#), 4XSLT (Python), xsltProc/xsltLib ( C ), Xalan J 2.4.1 (Java).

I don't claim that the results are 100% correct or that XSLT processor X is much faster than an XSLT processor Y. I encourage readers are encouraged to perform their own tests. However, I believe that these results would be useful both to users and developers of XSLT processors -- in choosing a suitable XSLT processor that supports EXSLT or in further improving the EXSLT implementation of such a processor.

As can be seen from the results, exMSXML4 ran considerably faster than 5 of the 8 tested implementations, which were written in Java, Python, C#, and C.

exMSXML4 was slower only compared to Xalan C 1.5 and Saxon 6.5.2 (although it was faster than Saxon on set:leading() and set:trailing() and faster than both Xalan C 1.5 and Saxon 6.5.2 on set:has-same-node()).

The actual tests are provided in the Appendix. They were run on a 1.7GHz Pentium 4 with 256MB of RAM. All results are in milliseconds.

The results are summarized in the two tables below:

Time Comparison between different implementations of EXSLT

1. With a node-set of 10000 nodes
Implementation Intersection difference leading trailing distinct Has-same-node Total Average
Xalan C 1.5 80 80 10 15 50 58 293 49
Saxon 6.5.2 170 170 140 140 160 150 930 155
exMsxml 4 1391 1524 29 23 4468 46 7481 1247
JD 3095 3635 170 140 12117 150 19307 3218
4XSLT 6840 7400 891 871 751 6930 23323 3887
.Net xslTransform 5802 5832 22 22 10696 6558 28932 4822
xsltProc 37674 40808 20549 20429 20830 44754 185044 30840
Xalan J 2.4.1 2013 2003 181220 43653 1112 1122 231123 38520


2. With a node-set of 2000 nodes
Implementation Intersection difference leading trailing distinct Has-same-node Total Average
Xalan C 1.5 15 13 1 1 10 10 50 8
Saxon 6.5.2 31 30 30 20 30 20 161 27
exMsxml 4 72 75 11 9 238 14 419 70
.Net xslTransform 115 115 12 11 368 140 761 127
JD 140 160 80 80 370 100 930 155
4XSLT 460 460 150 150 140 471 1831 305
xsltProc 430 430 210 210 250 570 2100 350
Xalan J 2.4.1 921 901 6709 2733 832 871 12967 2161

Conclusion

This article described a general way to obtain an instance of a non-creatable object by using a callback. I have shown how to build an efficient XSLT application by improving an algorithm step by step. I demonstrated several optimization techniques: binary search, DVC, using keys, and elimination of recursion. The test results show that this XSLT-based implementation of the Sets module of EXSLT is faster than five other implementations written in Python, Java, C, and C#.

Appendix -- the tests code

  1. The two source xml documents, on which the tests were performed look like this:

    nums10000.xml:
    <Nums>
      <Num>1</Num>
      <Num>2</Num>
      <Num>3</Num>
    .  .  .  .  .  .  .  .  .
      <Num>9998</Num>
      <Num>9999</Num>
      <Num>10000</Num>
    </Nums>
    

    Nums2000.xml:
    <Nums>
      <Num>1</Num>
      <Num>2</Num>
      <Num>3</Num>
    .  .  .  .  .  .  .  .  .
      <Num>1998</Num>
      <Num>1999</Num>
      <Num>2000</Num>
    </Nums>
    


  2. Testing set:intersection() -- testExsltIntersect.xsl:
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:set="http://exslt.org/sets">
     
     <xsl:output omit-xml-declaration="yes"/>
     
      <xsl:template match="/">
        <xsl:variable name="v2" select="/*/*[. mod 2 = 0]"/>
        <xsl:variable name="v3" select="/*/*[. mod 3 = 0]"/>
        
        <xsl:variable name="vIntersect" select="set:intersection($v2, $v3)"/>
        
        <xsl:copy-of select="$vIntersect[1]"/>
    
      </xsl:template>
    </xsl:stylesheet>
    


  3. Testing set:difference() -- testExsltDifference.xsl:
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:set="http://exslt.org/sets">
     
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     
      <xsl:template match="/">
        <xsl:variable name="v2" select="/*/*[. mod 2 = 0]"/>
        <xsl:variable name="v3" select="/*/*[. mod 3 = 0]"/>
        
        <xsl:variable name="vDifference" select="set:difference($v2, $v3)"/>
        <xsl:copy-of select="$vDifference[1]"/>
    
      </xsl:template>
    </xsl:stylesheet>
    


  4. Testing set:leading() -- testLeading.xsl:
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:set="http://exslt.org/sets">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     
      <xsl:template match="/">
        <xsl:copy-of select="set:leading(/*/*, /*/*[last()])[1]"/>
      </xsl:template>
    </xsl:stylesheet>
    


  5. Testing set:trailing() -- testTrailing.xsl:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:set="http://exslt.org/sets">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     
      <xsl:template match="/">
        <xsl:copy-of select="set:trailing(/*/*, /*/*[1])[1]"/>
      </xsl:template>
    </xsl:stylesheet>
    


  6. Testing set:distinct() -- testEXSLTDistinct.xsl:
    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       xmlns:set="http://exslt.org/sets">
      <xsl:output omit-xml-declaration="yes" indent="yes"/>
      
      <xsl:template match="/">
        <xsl:copy-of select="set:distinct(/*/*)[1]"/>
      </xsl:template>
    </xsl:stylesheet>
    


  7. Testing set:has-same-node() -- testExsltSameNodes.xsl:
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:set="http://exslt.org/sets">
     
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     
      <xsl:template match="/">
        <xsl:variable name="v2" select="/*/*[. mod 2 = 0]"/>
        <xsl:variable name="v3" select="/*/*[. mod 3 = 0]"/>
        <xsl:variable name="v4" select="/*/*[7]"/>
        
        <xsl:variable name="vbSame23" select="set:has-same-node($v2, $v3)"/>
        
        set:has-same-node(/*/*[. mod 2 = 0], /*/*[. mod 3 = 0]) = <xsl:text/>
        
        <xsl:copy-of select="$vbSame23"/>
        
        <xsl:text>&#160;</xsl:text>
        <xsl:text>&#160;</xsl:text>
        
        <xsl:variable name="vbSame24" select="set:has-same-node($v2, $v4)"/>
        
        set:has-same-node(/*/*[. mod 2 = 0], /*/*[7]) = <xsl:text/>
        
        <xsl:copy-of select="$vbSame24"/>
      </xsl:template>
    </xsl:stylesheet>
    





1 to 1 of 1
  1. Missing source?
    2003-08-07 11:51:13 not right
1 to 1 of 1