<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |
<html> | |
<head> | |
<title>ASF: XSLTC Performance</title> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<meta http-equiv="Content-Style-Type" content="text/css" /> | |
<link rel="stylesheet" type="text/css" href="resources/apache-xalan.css" /> | |
</head> | |
<!-- | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
--> | |
<body> | |
<div id="title"> | |
<table class="HdrTitle"> | |
<tbody> | |
<tr> | |
<th rowspan="2"> | |
<a href="../index.html"> | |
<img alt="Trademark Logo" src="resources/XalanJ-Logo-tm.png" width="190" height="90" /> | |
</a> | |
</th> | |
<th text-align="center" width="75%"> | |
<a href="index.html">XSLTC Design</a> | |
</th> | |
</tr> | |
<tr> | |
<td valign="middle">XSLTC Performance</td> | |
</tr> | |
</tbody> | |
</table> | |
<table class="HdrButtons" align="center" border="1"> | |
<tbody> | |
<tr> | |
<td> | |
<a href="http://www.apache.org">Apache Foundation</a> | |
</td> | |
<td> | |
<a href="http://xalan.apache.org">Xalan Project</a> | |
</td> | |
<td> | |
<a href="http://xerces.apache.org">Xerces Project</a> | |
</td> | |
<td> | |
<a href="http://www.w3.org/TR">Web Consortium</a> | |
</td> | |
<td> | |
<a href="http://www.oasis-open.org/standards">Oasis Open</a> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
<div id="navLeft"> | |
<ul> | |
<li> | |
<a href="index.html">Overview</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="xsltc_compiler.html">Compiler design</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="xsl_whitespace_design.html">Whitespace</a> | |
</li> | |
<li> | |
<a href="xsl_sort_design.html">xsl:sort</a> | |
</li> | |
<li> | |
<a href="xsl_key_design.html">Keys</a> | |
</li> | |
<li> | |
<a href="xsl_comment_design.html">Comment design</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="xsl_lang_design.html">lang()</a> | |
</li> | |
<li> | |
<a href="xsl_unparsed_design.html">Unparsed entities</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="xsl_if_design.html">If design</a> | |
</li> | |
<li> | |
<a href="xsl_choose_design.html">Choose|When|Otherwise design</a> | |
</li> | |
<li> | |
<a href="xsl_include_design.html">Include|Import design</a> | |
</li> | |
<li> | |
<a href="xsl_variable_design.html">Variable|Param design</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="xsltc_runtime.html">Runtime</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="xsltc_dom.html">Internal DOM</a> | |
</li> | |
<li> | |
<a href="xsltc_namespace.html">Namespaces</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="xsltc_trax.html">Translet & TrAX</a> | |
</li> | |
<li> | |
<a href="xsltc_predicates.html">XPath Predicates</a> | |
</li> | |
<li> | |
<a href="xsltc_iterators.html">Xsltc Iterators</a> | |
</li> | |
<li> | |
<a href="xsltc_native_api.html">Xsltc Native API</a> | |
</li> | |
<li> | |
<a href="xsltc_trax_api.html">Xsltc TrAX API</a> | |
</li> | |
<li>Performance Hints<br /> | |
</li> | |
</ul> | |
</div> | |
<div id="content"> | |
<h2>XSLTC Performance</h2> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Introduction</h3> | |
<p> | |
<b>XSLT is not a programming language!</b> Just so you remember. | |
XSLT is a declarative language and can be used by you to describe | |
<b>what</b> you want put in your output document and | |
<b>what</b> you want this output to look like. It does not describe | |
<b>how</b> these tasks should be carried. That is the job of the XSLT | |
processor. This document is <b>not</b> a "<b> | |
<i>programmer's guide to XSLT</i> | |
</b>" | |
and should not be considered as such. All XSLT processors have their | |
properties and ways of handling XSL elements and XPath properties. This | |
document will give you some insight into the XSLTC internals, so that you | |
can channel your stylesheets through XSLTC's shortest and most efficient | |
code paths.</p> | |
<p>XSLTC's performance has always been one of its key selling points. | |
(I should probably find a better term here, since we're giving XSLTC away | |
for free.) But, there are some specific patterns and expressions that are | |
not handled much better than with other interpretive XSLT processors, and | |
this document is an attempt to pinpoint these and to outline alternatives. | |
</p> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Contents</h3> | |
<ul> | |
<li> | |
<a href="#pred">Avoid using predicates in '*' patterns</a> | |
</li> | |
<li> | |
<a href="#idkey">Avoid using id/key-patterns</a> | |
</li> | |
<li> | |
<a href="#union">Avoid union expressions where possible</a> | |
</li> | |
<li> | |
<a href="#sort">Sort stored node-sets once</a> | |
</li> | |
<li> | |
<a href="#cache">Cache input documents</a> | |
</li> | |
<li> | |
<a href="#trax">TrAX vs. native API</a> | |
</li> | |
</ul> | |
<a name="pred"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Avoid using predicates in wildcard patterns</h3> | |
<p>XSLTC gains its speed from the simple dispatch loop in the translet's | |
<code>applyTemplates()</code> method. This method uses a simple | |
<code>switch()</code> statement to choose the desired template based on | |
the current node's node type (an integer). By adding a pattern with a | |
wildcard (no type) and a predicate, XSLTC is forced to evaluate the | |
predicate for every single node.</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:template match="*[2]"></pre> | |
</blockquote> | |
<p>The above pattern should be avoided by selecting the desired node when | |
using <code><xsl:apply-templates></code>. Use named templates or | |
modes to make sure you trigger the correct template:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:template match="/"> | |
<xsl:apply-templates select="bar"/> | |
</xsl:template> | |
<xsl:template match="*[2]"/> | |
<xsl:template match="*"/></pre> | |
</blockquote> | |
<p>can be replaced by:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:template match="/"> | |
<xsl:apply-templates select="bar"/> | |
<xsl:apply-templates select="bar[2]" mode="second"/> | |
</xsl:template> | |
<xsl:template match="*" mode="second"/> | |
<xsl:template match="*"/></pre> | |
</blockquote> | |
<p>This change will only improve performance if the stylesheet is fairly | |
large and has a good few templates (10 or more). Also note that the order | |
of the output is changed by this approach, so if the order is significant | |
you'll have to stick to the original stylesheet.</p> | |
<p> | |
<b>Important note:</b> The type of pattern referred to as a | |
type-less pattern, as it does not match any specific node type. Such | |
patterns do in general degrade the performance of XSLTC. Type-less patterns | |
must be evaluated for every single node in the input document - causing a | |
general performance degradation.</p> | |
<a name="idkey"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Avoid using id/key-patterns</h3> | |
<p>Id and key patterns can be used to trigger a template if the current | |
node has a specific id or has a specific value in a key's index:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:template match="id('some-value')"/> | |
<xsl:template match="key('key-name', 'some-value')"/></pre> | |
</blockquote> | |
<p>Looking up a value/node-pair in an index does not require much processing | |
time at all. But, this is also a type-less pattern and can match any type | |
of node. This degrades XSLTC's performance, just like wildcard patterns | |
with predicates (see above paragraph).</p> | |
<a name="union"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Avoid union expressions where possible</h3> | |
<p>Union expressions provide an all-in-one-go easy way of applying templates | |
to sets of nodes:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:apply-templates select="foo|bar|baz"/></pre> | |
</blockquote> | |
<p>The union iterator that is used to implement union expressions is | |
unfortunately not very efficient. If node order is not of importance, then | |
one can benefit from breaking the union up in several elements:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:apply-templates select="foo"/> | |
<xsl:apply-templates select="bar"/> | |
<xsl:apply-templates select="baz"/></pre> | |
</blockquote> | |
<p>But, remeber that this will give you all <code><foo></code> | |
elements first, then all <code><bar></code> elements, and so on. | |
This is not always desirable. You may want to handle these elements in | |
the order in which they appear in the input document.</p> | |
<p> | |
<b>Important note:</b> This does <b>not</b> apply to union patterns. | |
Using unions in patterns actually makes smaller and more efficient code, | |
as only one copy of the templete body has to be compiled. Use:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:template match="foo|bar|baz"/></pre> | |
</blockquote> | |
<p>instead of:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:template match="foo"/> | |
<xsl:template match="bar"/> | |
<xsl:template match="baz"/></pre> | |
</blockquote> | |
<a name="sort"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Sort stored node-sets once</h3> | |
<p>This item is very obvious, but nevertheless easy to forget in some | |
complicated cases. If you put a result-tree fragment inside a variable, and | |
you want the nodes in a specific, sorted order, then sort the nodes as you | |
create the variable and not when you use it. Instead of:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:variable name="bars"> | |
<xsl:copy-of select="//foo/bar"/> | |
</xsl:variable> | |
<xsl:template match="/"> | |
<xsl:text>List of bar's in sorted order:&#xa;</xsl:text> | |
<xsl:for-each select="$bars-sorted"> | |
<xsl:value-of select="@name"/> | |
<xsl:text>&#xa;</xsl:text> | |
</xsl:for-each> | |
</xsl:template></pre> | |
</blockquote> | |
<p>A better way, and with most XSLT processors the only legal way, is to | |
sort the result tree when creating it:</p> | |
<blockquote class="source"> | |
<pre> | |
<xsl:variable name="bars"> | |
<xsl:for-each select="//foo/bar"> | |
<xsl:sort select="@name"/> | |
<xsl:copy-of select="."/> | |
</xsl:for-each> | |
</xsl:variable> | |
<xsl:template match="/"> | |
<xsl:text>List of bar's in sorted order:&#xa;</xsl:text> | |
<xsl:for-each select="$bars"> | |
<xsl:value-of select="@name"/> | |
<xsl:text>&#xa;</xsl:text> | |
</xsl:for-each> | |
</xsl:template></pre> | |
</blockquote> | |
<p>It is very common to sort node-sets returned by the id() and key() | |
functions. Instead of doing this sorting over and over again, one should | |
use a variable and store the node set in the desired sort order, and read | |
the node set from the variable whenever used.</p> | |
<a name="cache"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Cache the input document</h3> | |
<p>All XSLT processors use an internal DOM-like structure, and XSLTC is no | |
exception. The internal DOM is tailored for the XSLTC design and can be | |
navigated efficiently by the translet. Building the internal DOM is a | |
rather slow process, and does very many cases take more time than the | |
actual transformation. This is a general rule, and does not only apply to | |
XSLTC. It is advisable, and common in most large-scale XSLT-based | |
applications, to create a cache for the input documents. Not only does this | |
prevent CPU- and memory-intensive DOM creation, but it also prevents several | |
translets from having their own private copies of common input documents. | |
Both XSLTC's internal API and TrAX implementation provide ways of | |
implementing a decent input document cache:</p> | |
<ul> | |
<li>See <a href="#trax-cache">below</a> for a description of how | |
to do this using the TrAX interface.</li> | |
<li>The <a href="xsltc_native_api.html#document-locator">native API | |
documentation</a> contains a section on using the internal | |
<code>org.apache.xalan.xsltc.compiler.SourceLoader</code> interface.</li> | |
</ul> | |
<a name="trax"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>TrAX vs. native API</h3> | |
<h5>TrAX performance benefits</h5> | |
<p>If XSLTC's two-step approach to XSLT processing suits your application | |
then there is no reason why you should not use the TrAX API. The API fits | |
very nicely in with XSLTC internals and processing model. In fact, you may | |
even benefit from using TrAX in cases where your stylesheet is compiled | |
into a large ammount of auxiliary classes. The most obvious benefit is that | |
the translet class and auxiliary classes are all bundled inside the | |
<code>Templates</code> object. Performance can also be improved due to the | |
fact that XSLTC chaches all auxiliary classes inside <code>Templates</code> | |
code, preventing the class loader from being invoked more than necessary. | |
This is just theory and no tests have been done, but you should see a | |
performance improvement when using XSLTC and TrAX in such cases.</p> | |
<h5>Treat Templates objects as compiled translets</h5> | |
<p>When using TrAX, the <code>Templates</code> object should be considered | |
the result of a compilation. With XSLTC this is the actual case - the | |
<code>Templates</code> object contains the translet Java class(es). With | |
other XSLT processors the <code>Templates</code> directly or indirectly | |
contains data-structures represent all or parts of the input stylesheet. | |
The bottom line is: Create your <code>Templates</code> object once, cache | |
and re-use it as often as possible.</p> | |
<a name="trax-cache"></a> | |
<h5>Input document caching</h5> | |
<p>An extension to the TrAX API allows input documents to be cached. The | |
extensions is a sub-class to the TrAX <code>Source</code> class, which can | |
be used to wrap XSLTC's internal DOM structures. This is described in | |
detail in the <a href="xsltc_trax_api.html">XSLTC TrAX API reference</a>. | |
</p> | |
<p>If you do chose to implement a DOM cache, you should have your cache | |
implement the <code>javax.xml.transform.URIResolver</code> interface so | |
that documents loaded by the <code>document()</code> function are also read | |
from your cache.</p> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
</div> | |
<div id="footer">Copyright © 1999-2012 The Apache Software Foundation<br />Apache, Xalan, and the Feather logo are trademarks of The Apache Software Foundation<div class="small">Web Page created on - Fri 07/13/2012</div> | |
</div> | |
</body> | |
</html> |