Optimizations and performance improvements
The code for
<xsl:number level="any"> has been optimized. The conditions that must apply
for this optimization are
that the count and from patterns must not contain any variable references; either the count pattern must
be specified, or the name and type of the context node must be statically obtainable, typically from
the match pattern of the containing template rule. Under these circumstances, Saxon will remember the
result of evaluating the instruction, and the next time it is evaluated, if the first node encountered
in its reverse scan of the document is the one that was most recently numbered, it will simply add one
to the remembered number.
Note: a similar optimization for
<xsl:number> with no attributes has been
in use for some time.
The numbering code also now passes down the required node name and kind to the axis iterator that is used to find the nodes being counted. This reduces the overhead of skipping non-matching nodes.
The code for navigating the parent and ancestor axes in the TinyTree implementation has been improved. The next pointer for the last sibling now points to the parent node; this is distinguished from a normal next pointer by virtue of the fact that it always points backwards in the node array. When a search is needed to find the parent, this is now done by reading the next-sibling pointer chain until the owner is found, which in general is faster than the previous technique, of scanning all preceding nodes until one is found whose depth is lower.
This was done after exploring a number of alternative approaches, none of which led to significant performance improvements. In particular, I tried various ways of remembering the parent node during a scan of the descendant axis, but in all cases the benefit achieved when the parent node was actually used was less than the extra cost of maintaining the information in the cases where it wasn't needed.
Note: I have not identified any circumstances in which the "standard" tree implementation out-performs the TinyTree. The "standard" implementation is retained, however, because it is used for stylesheets during compilation.
A small improvement has been made to the code for evaluating an attribute reference.
Various expression classes now contain their own implementations of the effectiveBooleanValue() method, avoiding the need to use the general-purpose logic in cases where the value is already known to be a singleton.
My main test case for these performance improvements was the stylesheet used to render the XSLT 2.0 specification. The execution time for this stylesheet improved from 16.4 seconds to 7.6 seconds. Improvements for other stylesheets are very unlikely to be as high as this. Another test case improved from 66.8 to 59.8 seconds, which is probably more typical.