INFO: Techniques to Improve Performance of XSL Transformations (815124)



The information in this article applies to:

  • Microsoft .NET Framework Class Libraries 1.0
  • Microsoft .NET Framework Class Libraries 1.1
  • Microsoft .NET Framework 1.0
  • Microsoft .NET Framework 1.1

SUMMARY

This article lists some techniques to improve the performance of Extensible Stylesheet Language (XSL) Transformations. XSL is a functional language. XSL does not support features of common language. For example, XSL does not support return values, or globals. XSL is not an object-oriented language, and being modular costs processor cycles. There is no debug available for XSL, therefore, the debugging becomes difficult.

MORE INFORMATION

Performance of an XSL transformation depends on the scenarios that you use. The techniques that are listed in this article are general guidelines. Make sure that you measure the results of each tuning. Only testing can prove whether a particular technique improves the performance or not. You can use the msxsl.exe command line utility for testing, and to perform command line XSL transformations by using the Microsoft XSL processor. The msxsl.exe utility invokes the Microsoft XML Parser 4.0 (msxml4.dll) to perform the transformation. You can download this utility from the following MSDN site:

Techniques to Improve the Performance

  • Identify the most common code paths to render your pages, and then optimize these paths. Optimize the highly re-used sections of XSL.
  • Instead of using sub-elements, use attributes wherever possible. Using attributes instead of elements improves the performance. When performing XPath matches, attributes are faster because they are loosely typed. This makes validation of the schema easier.
  • Use more explicit paths instead of "//" wherever possible. When XML data is large, "//" recursive decedent search is very expensive. Specific XPath expression implements faster.
  • When you match against attribute values, use enumerator attributes. Use multiple attribute names as bits, and set their values to true or false. For example:
    <element_name attr1="1" attr2="1" attr3="0">
  • Do not use script. Using script downgrades the performance.
  • Compare directly by name to improve the performance. For example, instead of using the following code:
    ./info[type='title']
    use the following code:
    ./title
    When you compare values, instead of using name as follows:
    Select="*[name()='sample']"
    use the following code:
    Select="sample"
    Because of the namespace handling in XPath, these are not exactly equivalent.
  • All versions of MSXML, Version 3.0 and later, are faster with the explicit index filter. The improvement in performance depends on the position of the element in the child list of the parent. Instead of using the following:
    /child_element
    use the following:
    /child_element[1]
  • Use parameters instead of evaluating the query each time.
  • XSL Transformations allows multiple options, however, all of them may not perform adequately. For example, instead of using the following transformation:
    <xsl:output method="html"/>
    use the following transformation:
    <xsl:output method="html" indent="no" />
    This improves performance because indentation provides a lot of unwanted white spaces in the output. By default, the value for the attribute indent is yes.
  • Inline the template with for-each or mode attribute when you are sure that your apply-template matches exactly one template. For example:
    <xsl:apply-templates select="//xa:Axes/xa:Axis[@name='Axis1']" />
    <xsl:template match="//xa:Axis[@name='Axis1']/xa:Tuples/xa:Tuple">
    For each node that matches the following:
    "//xa:Axes/xa:Axis[@name='Axis1']"
    the following expression:
    "//xa:Axis[@name='Axis1']/xa:Tuples/xa:Tuple"
    is evaluated on all other templates with the same mode. Processor starts to run default templates. This copies all text nodes, and calls the following:
    <xsl:apply-templates>
    for all elements. Therefore, for all children of original nodeset, possible matches expression is evaluated. Matching the expression is not a simple task. To improve the performance, rewrite the code as follows:
    <xsl:apply-templates select="//xa:Axes/xa:Axis[@name='Axis1']/xa:Tuples/xa:Tuple" mode="Axis1"/>
    <xsl:template match="*" mode="Axis1">
  • Use fewer templates. This is applicable when you run the same template more than one time. There is some improvement in performance with tight for-each loop to search for a template when the number of templates are less.
  • Reduce the usage of xsl:choose/xsl:when/xsl:otherwise. Performance is effected when the majority of selections fall through the otherwise clause. Therefore, match with when, and try to avoid using otherwise when you know that a particular value exists.
  • xsl:variables are dynamic values. These variables are not in cache, and run every time that they are referenced in XSL. Explicit type casting of xsl:variable improves the performance. You can do type casting with string() and boolean() functions. For example:
    <xsl:variable name="_attr" select="string( /node/child[ @attr ] )">
  • MSXML Vs. System.Xml
    • MSXML parser is different from XmlReader and XmlWriter.
    • MSXML loads XML data into a Document Object Model (DOM). From this DOM tree, data can easily be navigated through XPath, transformed through XSL, or edited and saved back. This enables easier development and more powerful capabilities at the expense of memory usage and speed.
    • XmlReader and XmlWriter are sequential readers and writers. The developer maintains state manually when reading and writing XML data. This allows the minimal memory usage and, therefore, improves the performance.
    • The MSXML parser also supports SAX (Simple API for XML). SAX is sequential. The .NET framework also supports the DOM by using the XmlDocument class.
    • The best choice depends on the utilization of .NET framework and on the task that you perform with XML.
  • This technique is related to the performance with database. MSXML and System.Xml performance can be improved in pre-joining the lookup fields as shown in the following code:
    <?xml version="1.0" encoding="UTF-8"?>
    <AllLocalDescriptor xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
    <Descriptor key="AMC_Labels_" ID="AMC" Name="-2000" TypeName="Labels" LCID="">
      AMC
    </Descriptor>
    <Descriptor key="AMC_Labels_3082" ID="AMC" Name="-2000" TypeName="Labels" LCID="3082">
      AMC
    </Descriptor>
    You can avoid scanning by declaring @key of type ID.
    desc = doc.getNodeFromID("AMC_Labels_3082")

REFERENCES

For more information, visit the following Microsoft Developer Network (MSDN) Web sites: For additional information about performance of XSLT, click the following article numbers to view the articles in the Microsoft Knowledge Base:

325689 INFO: Performance of XSLT Transformations in the .NET Framework

331026 Show Me How: Performance tune my Xslt Stylesheet in .NET using System.Xml


Modification Type:MinorLast Reviewed:5/12/2003
Keywords:kbPerformance kbXML kbinfo KB815124 kbAudDeveloper