fn:matches()与=的XSLT性能

时间:2017-05-18 16:40:02

标签: xml xslt xpath saxon

对于平等与fn:matches()之间的性能差异感到好奇,我运行了以下测试:

<xsl:variable name="limit" select="123456789"/>
<xsl:template match="/*">
    <xsl:copy>
        <xsl:value-of
            select="
                count(for $i in (1 to $limit)
                return
                    if ('m' = 'm') then
                        true()
                    else
                        ())"/>
        <xsl:value-of
            select="
                count(for $i in (1 to $limit)
                return
                    if (matches('m', 'm')) then
                        true()
                    else
                        ())"
        />
    </xsl:copy>
</xsl:template>

通过Saxon HE / PE 9.7.0.15处理,<value-of>在我的Mac上运行6.9秒。单独运行,第一个运行5.2秒,第二个运行1.8秒。这对我来说似乎不直观。为什么平等需要更长时间来评估而不是匹配?

这种差异在所有情况下都是相同的吗?也就是说,选择fn:matches()而非=(显然,对于字符串比较)通常可以提高性能吗?

更新:在Saxon EE下,测试加速并平衡:分别为5.1 / 2.5 / 2.5秒。它仍然留下了一个原始问题,即为什么表面上看起来更简单的操作会比更复杂的操作更长或更长。

1 个答案:

答案 0 :(得分:1)

我怀疑你的测量是有缺陷的:通常的错误是无法允许Java预热时间,所以实际上你只是测量Java加载需要多长时间。尝试使用命令行选项-repeat:50来查看此效果。

另一个问题是你的“=”和“匹配”调用都有常量参数,这意味着表达式将在编译时被评估一次。

Saxon实际生成的执行计划是这样的(对于两个指令值都是相同的):

<fn name="count">
 <for var="i" as="xs:integer" slot="0">
  <range role="in" from="1" to="123456789"/>
  <true role="return"/>
 </for>
</fn>

也就是说,它已将两个表达式都缩减为

count(for $i in 1 to 123456789 return true())

(这解释了为什么两者都在同一时间执行),这将是一个非常短的步骤,以进一步优化

123456789