Subject: Re: [xsl] Performance improvement for a recursive function? From: Andrew Welch <andrew.j.welch@xxxxxxxxx> Date: Tue, 13 Dec 2011 09:52:49 +0000 |
fwiw, there are further slight tweaks of use xsl:sequence instead of xsl:value-of (to avoid the text node creation and then atomization to a string), and moving the sequences into variables, eg change $cmd = (' ', 'M', 'l', 'm') to $cmd = $seq where $seq is <xsl:variable name="seq" select="(' ', 'M', 'l', 'm')" as="xs:string+"/> To tweak that a bit more, you could use the code points instead of the characters... but it might not be worth it. On 13 December 2011 09:44, Manfred Staudinger <manfred.staudinger@xxxxxxxxx> wrote: > Hi Wolfgang, > > What a great solution: execution time is down to 7 sec (from 14 minutes). > Thanks a lot, > > Manfred > > On 13/12/2011, Wolfgang Laun <wolfgang.laun@xxxxxxxxx> wrote: >> I forgot to mention that the result of this function must be processed with >> string-join(my:compose-path-data($Data),'') >> -W >> >> On 13 December 2011 08:46, Wolfgang Laun <wolfgang.laun@xxxxxxxxx> wrote: >>> This function permits processing of all contained commands. >>> >>> I don't have the time to analyze what should be done for each; I saw >>> that m0,0 was dropped. >>> >>> It's fast enough now :-) >>> >>> -W >>> >>> <xsl:function name="my:compose-path-data" as="xs:string*"> >>> <xsl:param name="data" as="xs:string*"/> >>> <xsl:analyze-string select = "$data" >>> regex = "[ Mlm](\d+),(\d+)|[hv](\d+)|z"> >>> <xsl:matching-substring> >>> <xsl:variable name="cmd" select="substring(regex-group(0),1,1)"/> >>> <xsl:choose> >>> <xsl:when test="$cmd = (' ', 'M', 'l', 'm')"> >>> <xsl:value-of >>> select="concat($cmd,regex-group(1),',',regex-group(2))"/> >>> </xsl:when> >>> <xsl:when test="$cmd = ('h', 'v')"> >>> <xsl:value-of select="concat($cmd,regex-group(3))"/> >>> </xsl:when> >>> <xsl:when test="$cmd = 'z'"> >>> <xsl:value-of select="$cmd"/> >>> </xsl:when> >>> </xsl:choose> >>> </xsl:matching-substring> >>> </xsl:analyze-string> >>> </xsl:function> >>> >>> >>> On 13 December 2011 01:07, Manfred Staudinger >>> <manfred.staudinger@xxxxxxxxx> wrote: >>>> Hi, >>>> >>>> I need some help to improve the performance of a function, as I have >>>> run out of ideas what to change! >>>> >>>> In the process to convert some data to SVG I transform (or even break >>>> up) @Data attribute of the Path element and then use the function >>>> my:compose-path-data [1] to put the parts together into a string >>>> again. The attribute string is a succession of path commands, where >>>> each path command (see the global variable below) consists of a one >>>> byte character followed by zero, one, or two integers. Having about >>>> 2200 Path elements, most of them have a @Data attribute with between 5 >>>> an 50 path commands. >>>> >>>> A few attribute strings are bigger (up to 1MB) and contain up to >>>> 100000 path commands. As the function is called for each path command >>>> it is tail recursive, but the performance is still a big problem: to >>>> process 41337 path commands it takes 861 sec! The first 5000 path >>>> commands are processed in 14 sec (at 355.87 per sec) the last 5000 >>>> take 671 sec (only at 7.5 per sec). >>>> >>>> What Saxon reports [2] is consistent with the above. In case you want >>>> to try it, I have uploaded the specific test case here: >>>> http:///test.rudolphina.org/test01-perform-data.xsl >>>> http:///test.rudolphina.org/test01-perform-data-org.xml >>>> >>>> Using Saxon-HE 9.3.0.5J and Java version 1.6.0_14 on Windows. XP Home. >>>> Hardware ASUS Eee PC 1000H with Intel. Atom N270 (1.60 GHz) >>>> >>>> Regards, >>>> Manfred >>>> >>>> [1] >>>> <xsl:function name="my:compose-path-data" as="xs:string*"> >>>> <xsl:param name="c" as="xs:integer*"/> >>>> <xsl:param name="i-c" as="xs:integer"/> >>>> <xsl:param name="xy" as="xs:integer*"/> >>>> <xsl:param name="i-xy" as="xs:integer"/> >>>> <xsl:param name="i-end" as="xs:integer"/> >>>> <xsl:param name="result" as="xs:string?"/> >>>> <xsl:variable name="cmd" select="key('path', $c[$i-c], $path-cmd)" >>>> as="element()?"/> >>>> <xsl:sequence select="if ($i-c gt $i-end) >>>> then $result >>>> else my:compose-path-data($c, $i-c + 1, >>>> $xy, $i-xy + xs:integer($cmd/n), >>>> $i-end, >>>> concat($result, $cmd/@char, if ($cmd/n=2) >>>> then (: M, m, l, (blank) :) concat($xy[$i-xy], ',', >>>> $xy[$i-xy+1]) >>>> else if ($cmd/n=1) >>>> then (: h, v :) string($xy[$i-xy]) >>>> else (: z :) ()) >>>> )"/> >>>> </xsl:function> >>>> >>>> and on the stylesheet level >>>> <xsl:variable name="path-cmd"> >>>> <path> >>>> <cmd char=" "><n>2</n><code>32</code></cmd> >>>> <cmd char="M"><n>2</n><code>77</code></cmd> >>>> <cmd char="l"><n>2</n><code>108</code></cmd> >>>> <cmd char="m"><n>2</n><code>109</code></cmd> >>>> <cmd char="h"><n>1</n><code>104</code></cmd> >>>> <cmd char="v"><n>1</n><code>118</code></cmd> >>>> <cmd char="z"><n>0</n><code>122</code></cmd> >>>> </path> >>>> </xsl:variable> >>>> <xsl:key name="path" match="cmd" use="xs:integer(code)"/><!-- $path-cmd >>>> --> >>>> >>>> [2] >>>> Stylesheet compilation time: 4218 milliseconds >>>> Using parser org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser >>>> net.sf.saxon.tree.tiny.TinyBuilder >>>> Tree built in 1375 milliseconds >>>> Tree size: 4 nodes, 0 characters, 11 attributes >>>> Execution time: 14m 31.579s (871579ms) >>>> Memory used: 36559128 >>>> NamePool contents: 33 entries in 33 chains. 8 prefixes, 8 URIs > -- Andrew Welch http://andrewjwelch.com
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Performance improvement f, Manfred Staudinger | Thread | Re: [xsl] Performance improvement f, Michael Kay |
Re: [xsl] Performance improvement f, Manfred Staudinger | Date | Re: [xsl] Performance improvement f, Michael Kay |
Month |