[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] How to output the start execution time and the end execution time?

Subject: Re: [xsl] How to output the start execution time and the end execution time?
From: "Abel Braaksma (Exselt) abel@xxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 6 Sep 2014 17:26:24 -0000

Actually, thinking about it, there is a problem with this approach and
Dimitre's approach. XSLT does not define the order of execution. In fact, the
sibling statements in the main code can take place in any order, or even in
parallel. To know the time that is taken to process your XSLT, your best bet
is to use internal counters that your processor provides that remove the JIT,
static analysis, XPath parsing and other preprocessing times from your

Provided you want an XSLT solution, we must force the XSLT to apply an order
of processing by introducing dependencies.

The cleanest way I can think of is to use a new XSLT 3.0 concept for
accumulators: pre-descent and post-descent evaluation (i.e. before visiting a
node and after visiting a node, after means: after all children are

The problem with accumulators: it is a new XSLT 3.0 feature and currently no
processor fully supports them. However, it will work something like the
following (taking reported and resolved public bugs into account for the
syntax, search bugzilla for accumulators if you are interested).

To prevent optimizations (where functions can be pre-evaluated), let's take
Dimitre's approach and force evaluation on the right moment by making it
dependent on the visited node.

<!-- use streaming to force order of evaluation -->
<xsl:mode streamable="yes" />

<xsl:variable static="yes" name="timedocurl"
rmat=ms&amp;x=' " />

<!-- id-param is there  to prevent caching -->
<xsl:function name="my:time">
    <xsl:param name="id" as="xs:string" />
    <xsl:value-of select="
        doc($timedocurl || $id)/*/*:Timestamp/node()" />

<xsl:accumulator name="time" streamable="yes"
        select="my:time(generate-id(.))" />
        select="my:time(generate-id(.) || '-end')" />

<!-- do the normal processing (if necessary, change
   your templates to be properly streamable -->
<xsl:template match="/">
    <!-- this calls the pahase="start" accumulator rule -->
    <xsl:value-of select="'Start-time: ' || accumulator-before('time')" />
    <!-- regular processing -->
    <xsl:apply-templates />
    <!-- this calls the phase="end" accumulator rules -->
    <xsl:value-of select="'End-time: ' || accumulator-after('time')"/>

This approach works guaranteed cross-processor because the order of execution
is defined here: the processor *must* call the accumulator-after only after
all the processing is done (as a by-product, this means that accumulator-after
can only be called in post-descent instructions, meaning, *after* all children
are processed, which in this case is the following sibling of

This example can be extended to show the processing time of each visited node,
irrespective of optimizations. It is probably a good idea to use a local time
server / URI resolver though, so that time lag caused by networking is not
troubling the timings.

There are alternative ways of forcing the order of execution, but I thought
I'd use the opportunity to introduce accumulators. We currently support a
subset of them and are working on full support once the WG has cleared all
bugs on them.


Abel Braaksma
Exselt streaming XSLT 3.0 processor

> -----Original Message-----
> From: Abel Braaksma (Exselt) abel@xxxxxxxxxx [mailto:xsl-list-
> service@xxxxxxxxxxxxxxxxxxxxxx]
> Sent: Saturday, September 06, 2014 6:31 PM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Re: [xsl] How to output the start execution time and the end
> execution time?
> Hi Roger,
> Functions and constructs in XSLT and XPath are stable (barring a few
> exceptions). Calling a function with the same argument twice will yield the
> same result for both calls. The functions current-time(),
> and current-date() will therefor always return the same time (with a slight
> caveat for static and dynamic evaluation phases, but let's not digress).
> The only way out here is extension functions, or a trick with XSLT 3.0
> streaming, because the xsl:stream instruction is deemed non-stable (i.e.,
> will re-invoke the url at the href argument each time it is called). Whether
> extension function helps depends whether your processor allows non-stable
> extension functions, but I believe most, if not all, processors do.
> Here's a (workable) trick that works with all XSLT 3.0 processors, however
> you might want to choose a local resource instead that returns the current
> date-time, for performance reasons.
> <xsl:mode streamable="yes" name="time" on-no-match="shallow-skip" >
> <!-- may need an actual argument to force re-evaluation --> <xsl:function
> name="my:current-time">
>   <xsl:stream href="http://time.is">
>     <xsl:apply-templates mode="time" />
>   </xsl:stream>
> </xsl:function>
> <!-- match the element that contains the time --> <xsl:template
> match="div[@id = 'twd']">
>     <xsl:value-of select="." />
> </xsl:template>
> <xsl:template match="/">
>      <xsl:value-of select="my:current-time()" />
>      ... do the processing ...
>      <xsl:value-of select="my:current-time()" />  </xsl:template>
> Note: the page http://time.is currently does not deliver proper XML (and on
> my search for a time server that did deliver proper XML or even proper
> XHTML I did not find any). If you can convince your processor not to cache
> the result of unparsed-text, you can use the following with the same server
> as a workaround (ugly, but it shows the principle):
> <xsl:value-of select="replace(unparsed-text('http://time.is/'),
> '.+twd&quot;&gt;([^&lt;]+).*', '$1', 'sm')" />
> Cheers,
> Abel
> > -----Original Message-----
> > From: Costello, Roger L. costello@xxxxxxxxx [mailto:xsl-list-
> > service@xxxxxxxxxxxxxxxxxxxxxx]
> > Sent: Saturday, September 06, 2014 11:47 AM
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: [xsl] How to output the start execution time and the end
> > execution time?
> >
> > Hi Folks,
> >
> > I would like to:
> >
> > 1. Output the time that my XSLT program starts processing 2. Do the
> > processing 3. Output the time that my XSLT program finishes processing
> >
> > This doesn't work:
> >
> >     <xsl:template match="/">
> >         <xsl:value-of select="current-time()" />
> >         ... do the processing ...
> >         <xsl:value-of select="current-time()" />
> >     </xsl:template>
> >
> > What is the correct way to accomplish this?
> >
> > /Roger

Current Thread