Ha! Sorry, I messed up my example code. The actual code is a good deal more complicated and longer but has the same basic shape. At each step the called template takes some numeric parameters and a static set of data, modifies the numeric parameters based on some formula involving the current and calls itself with the new numeric parameters and the same static set of data.

You mention using "elements validated as numbers (by virtue of a schema)." I'll look into that. I must admit that I have never actually investigated the use of schema in my xsl . I use XSL as a general-purpose programming language (odd, I know) because I'd rather work in a language that has native Xpath in it than convert XML data first and then use Python, etc.  It wasn't clear to me how useful schema were for my purposes.

Here is a more coherent version of the same code I sent earlier. The difference is that $d has now been changed to $d/@x or $d/@y depending on the location.

I'm going to work up a simplified version of my actual code and send it out later... but I'm sending this just in case it clarifies what I had originally intended to ask.

<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/@x) div (abs($this.value * $d/@y) + 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>



On Sat, Feb 2, 2013 at 7:08 PM, Michael Kay <mike@saxonica.com> wrote:
I'm a bit confused by this code. $data is a set of elements having @x and @y elements. When you do


 for $d in $data return ($this.value + $d)

you're atomizing this element, which gives a zero-length string, and converting this to a number, which gives NaN.

Did you change the example for the sake of posting perhaps? If so, I think we need to see the real code, or at any rate, code which exhibits the problem. The optimizations Saxon does can be quite sensitive to small variations in the query.

You could certainly get some efficiency improvements by passing a sequence of numbers as the parameter value rather than a sequence of nodes from which numeric values need to be extracted. If you must use nodes, then using elements that are validated as numbers (by virtue of a schema) would help, because the conversion from string to number would only be done once for each node.

Michael Kay
Saxonica


On 02/02/2013 16:58, David Rudel wrote:
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.


------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_jan


_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
saxon-help@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/saxon-help 


------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_jan
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
saxon-help@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/saxon-help



--

"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.