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
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>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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> </xsl:text> <xsl:text> </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>
- Missing source?
2003-08-07 11:51:13 not right - Missing source?
2003-08-11 06:33:37 Dimitre Novatchev - re compiling
2003-08-11 13:05:27 James Fuller