Hi all,

I know that using keys can often massively improve the speed of stylesheets that require repeated querying of some XML document. I was wondering if there are any ways to speed up a stylesheet that repeatedly makes use of all the nodes of a (temporary) document or sequence without any querying or even interest in the order those nodes are processed.

I've provided a toy example below. The elements in the sequence $data are used over and over again to calculate new values using a (made-up) formula until those values converge.

Is there any way to speed up this process with the fore-knowledge that these nodes are going to be used over and over again, perhaps over 1000 times as the template calls itself?

Would use of a tunnel parameter make sense to alert the compiler that the same value for "$data" is going to be used in each recursive call as the template calls itself? I didn't use tunnel parameters because there are no middle-templates to tunnel through, so didn't think it matched the expected use case, but perhaps it would prevent the compiler from making 1000 copies of the same variable.

Also, (likely less important) is there any real performance difference between using the expression "sum(for $d in $data return .....) versus the expression sum($data/(......))?

Example:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:udf="user-defined"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"
    xmlns:err="http://www.w3.org/2005/xqt-errors"
    xmlns:math="http://exslt.org/math"
    xmlns:saxon="http://saxon.sf.net/"
    xmlns:exsl="http://exslt.org/common"
    xmlns:date="http://exslt.org/dates-and-times"
    exclude-result-prefixes="xs xdt udf saxon math fn err exsl date">

    <xsl:template match="/">
        <xsl:variable name="data" as="node()*">
            <point x="2" y="3"/>
            <point x="5" y="3"/>
            <point x="6" y="7"/>
            <point x="-3" y="8"/>
            <point x="6" y="-1"/>
            <point x="9" y="3"/>
            <point x="3" y="9"/>
            <point x="6" y="2"/>
        </xsl:variable>
        <xsl:for-each select="1 to 100">
            Starting Value=<xsl:value-of select="current()"/>
            <xsl:call-template name="process-step">
                <xsl:with-param name="last.value" select="0"/>
                <xsl:with-param name="this.value" select="current()"/>
                <xsl:with-param name="data" select="$data"/>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="process-step">
        <xsl:param name="last.value"/>
        <xsl:param name="this.value"/>
        <xsl:param name="data"/>
        <xsl:choose>
            <xsl:when test="abs($this.value - $last.value) lt 0.01">
                <xsl:text>
                </xsl:text>
                Final Value:<xsl:value-of select="$this.value"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:variable name="next.value" select="sum(for $d in $data return ($this.value + $d) div (abs($this.value * $d) + 1))"/>
                <xsl:call-template name="process-step">
                    <xsl:with-param name="last.value" select="$this.value"/>
                    <xsl:with-param name="this.value" select="$next.value"/>
                    <xsl:with-param name="data" select="$data"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>


Thanks!


--

"A false conclusion, once arrived at and widely accepted is not dislodged easily, and the less it is understood, the more tenaciously it is held." - Cantor's Law of Preservation of Ignorance.