RetroZilla/extensions/transformiix/docs/optimized-stylesheets.html
2015-10-20 23:03:22 -04:00

200 lines
6.4 KiB
HTML

<html>
<head>
<title>Optimizing Stylesheets</title>
<style>
.comment {
font-style: italic;
}
</style>
</head>
<body>
<h1>Optimizing Stylesheets</h1>
<h2>Overview</h2>
<p>
This document outlines optimizations that we can perform on
stylesheets after a stylesheet is compiled, but before it is executed.
</p>
<h2>Create AVTs out of xsl:attributes</h2>
<p>
People often write stylesheets like
<pre>
&lt;LRE&gt;
&lt;xsl:attribute name="foo"&gt;
text here
&lt;xsl:value-of select="@bar"/&gt;
&lt;/xsl:attribute&gt;
</pre>
This could be optimized into an AVT like
<pre>
&lt;LRE foo="text here{@foo}"&gt;
</pre>
This can be done both in templates and in attribute-sets
</p>
<h2>Investigate how RTFs are being used</h2>
<p>
When only the string-value or double-value of an RTF is being used it
is unneccesary to create an entire RTF. Instead we could set up a
string-handler and use the resulting string.
</p>
<p>
Once we have a node-set() function we could also have a special
handler that creates that resulting nodeset rather then
whatever-we-create-once-we-have-real-RTFs. That handler would be set
up when we can determain that a RTF is used only as argument to the
node-set() function.
</p>
<p>
In cases where an RTF is used as parameter in a call to another
template we could do further analysis to see how that parameter is
used in that template. Either by first analyzing how all template
parameters are used in all templates, or by recursivly searching
the called template when we find that a RTF is used as an argument.
</p>
<p>
We will still need a catch-all RTF implementation that is used when
we can't determin how a variable is used, or when it is used in
multiple different ways.
</p>
<h2>Inline/calculate constant variables</h2>
<p>
Variables that does not have a value that depends on the source
document can be inlined into the stylesheet. The value of these
variables could also be calculated before the transformation is
started.
</p>
<p>
This can be combined with the previous optimization of RTFs so that
stylesheets like
<pre>
&lt;xsl:variable name="v"&gt;_&lt;/xsl:variable&gt;
...
&lt;xsl:value-of select="concat(@id, $v, foo)"/&gt;
</pre>
is executed like
<pre>
&lt;xsl:value-of select="concat(@id, '_', foo)"/&gt;
</pre>
<p>
<p>
This can be done for both global and local variables.
</p>
<h2>Resolve cross-references</h2>
<p>
Cross-references to named templates, attribute-sets and template-modes
can be resolved before the stylesheet is executed. That way we don't
have to search for the template/attribute-set with a certain name, or
the group of templates for a certain mode.
</p>
<p>
Note that for apply-imports we won't always know at compile-time which
mode to seach for templates in.
</p>
<h2>Resolve variables by index rather then expanded name</h2>
<p>
Rather then seaching for variables with a certain name at runtime
we could remove names for variables/parameters entierly and put all
variables in an array (possibly a separate array for global variables)
and then let variable-references in expressions just point to an index
in that array.
</p>
<h2>Calculate and use constant AVTs</h2>
<p>
A lot of instruction-elements uses AVTs that often are constants in
stylesheets, such as the data-type parameter to xsl:sort. For xsl:sort
we could pre-create a finished nodesorter if all AVTs in all
xsl:sort-elements are constant.
</p>
<p>
Another example is xsl:element and xsl:attribute where we could use
LRE-instructions if the AVTs are constant. For xsl:number we could
create prepare the list of <code>txFormattedCounter</code>s.
</p>
<h2>Reuse parameter-map if exact same parameters are used</h2>
<p>
If a template calls another template and uses the exact same
parameters we can reuse the same parameter-map.
<pre>
&lt;xsl:template name="hsbc_html_body"&gt;
&lt;xsl:param name="appName"/&gt;
&lt;xsl:param name="title"/&gt;
&lt;body&gt;
&lt;xsl:call-template name="hsbc_form"&gt;
&lt;xsl:with-param name="appName" select="$appName"/&gt;
&lt;xsl:with-param name="title" select="$title"/&gt;
&lt;/xsl:call-template&gt;
&lt;/body&gt;
&lt;/xsl:template&gt;
</pre>
</p>
<p>
We have to watch out for default parameter-values as well as
parameters being specified by the caller of this template but not used
by this template. I.e. if the parameter "hello" is specified when
calling the above template.
</p>
<p class="comment">
All this might make this optimization useless.
</p>
<h2>Combind consecutive LRE items into a txResultBuffer</h2>
<p>
When a template contains several consecutive "LRE instructions" such
as LRE-elements, LRE-attributes and textnodes we can replace their
instructions with a special instruction that contains a
<code>txResultBuffer</code>. This buffer would then be flushed when
the instruction is executed. This can of course not be done for
LRE-attributes that contains AVTs. Even PI and comment-instructions
can be included in this buffer if their contents is strictly literal.
</p>
<p>
The result is that a template like
<pre>
&lt;xsl:template match="/"&gt;
&lt;html&gt;
&lt;body bgcolor="green"&gt;
Here goes pagecontent
&lt;xsl:apply-templates /&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/xsl:template&gt;
</pre>
Would result in the first <code>txResultBuffer</code> to contain the
following transactions: eStartElementTransaction,
eStartElementTransaction, eAttributeTransaction, eCharacterTransaction.
</p>
<p class="comment">
There is probably a lower limit to when it's worth the effort to
replace the normal instructions with the buffer-instruction. A single
"LRE instruction" is probobably better kept as a normal instruction.
</p>
</body>
</html>