xsl-list
[Top] [All Lists]

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

2014-09-06 12:26:37
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 
processing.  

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 processed).

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"
   select=" 
'http://developer.yahooapis.com/TimeService/V1/getTime?appid=YahooDemo&amp;format=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:function>

<xsl:accumulator name="time" streamable="yes"
    Initial-value="()">
    <xsl:accumulator-rule 
        match="/"
        phase="start"
        select="my:time(generate-id(.))" />
    <xsl:accumulator-rule 
        match="/"
        phase="end"
        select="my:time(generate-id(.) || '-end')" />
</xsl:accumulator>

<!-- 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')"/>
<xsl:template>


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 xsl:appy-templates).

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.

Cheers,

Abel Braaksma
Exselt streaming XSLT 3.0 processor
http://exselt.net



-----Original Message-----
From: Abel Braaksma (Exselt) abel(_at_)exselt(_dot_)net [mailto:xsl-list-
service(_at_)lists(_dot_)mulberrytech(_dot_)com]
Sent: Saturday, September 06, 2014 6:31 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
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(), current-dateTime()
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 using
streaming, because the xsl:stream instruction is deemed non-stable (i.e., it
will re-invoke the url at the href argument each time it is called). Whether 
an
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(_at_)mitre(_dot_)org [mailto:xsl-list-
service(_at_)lists(_dot_)mulberrytech(_dot_)com]
Sent: Saturday, September 06, 2014 11:47 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
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


--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>