提问人:Binsky 提问时间:3/13/2023 最后编辑:Martin HonnenBinsky 更新时间:3/14/2023 访问量:134
XSLT 3.0 流式处理 1000 的小型 XML 文件会提高性能吗?
XSLT 3.0 Will streaming of 1000's small XML files improve performance?
问:
我有一个大约 600K XML 文件的存储库,需要审核所有可能的值,这些文件通常很小,最大文件大小为 80k。<country name="Country_Name">
<country name="Country_Name">
保存在文章正文之前靠近顶部的 XML 元数据部分,使用流式处理方法是否会大大提高提取县值的性能,因为一旦 Xpath 发现该元素,流式处理就会停止?
这是正确的方法吗,如果是这样,我正在运行 Saxon 专业版,并且想知道流式传输大量小文档是否需要升级到企业版。
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode streamable="yes"/>
<xsl:template match="/">
<xsl:for-each-stream select="doc('file:///C:/temp/*.xml')">
<xsl:value-of select="//country"/>
<!-- Replace the following with your code to dump the current file -->
<xsl:message select="concat('Processing ', document-uri(.))"/>
</xsl:for-each-stream>
</xsl:template>
</xsl:stylesheet>
预期 打印到屏幕上的每条消息。
答:
我认为您可以使用例如
<xsl:template name="xsl:initial-template">
<xsl:for-each select="uri-collection('file:///C:/SomePath/SomeFolder?select=*.xml')">
<xsl:message expand-text="yes">Processing file {.}</xsl:message>
<xsl:source-document href="{.}" streamable="yes">
<xsl:value-of select="descendant::country[@name = 'Country_Name'][1]"/>
</xsl:source-document>
</xsl:for-each>
</xsl:template>
要使用流媒体,您需要 Saxon EE;如果要检查/测试该方法的性能是否优于传统的 XSLT 3,则可能需要向 Saxonica 申请试用许可证。
但是,我不确定发布的代码在找到第一个元素后是否停止处理文件;需要测试/检查;我认为撒克逊 EE 有一个 / 提前退出的地方。xsl:iterate
xsl:break
按照 https://www.saxonica.com/html/documentation11/streaming/partial-reading.html 的文档,我尝试了以下代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="uri" as="xs:string" expand-text="no">file:///C:/SomePath/SomeFolder?select=*.xml</xsl:param>
<xsl:param name="items-to-select" as="xs:integer" select="1"/>
<xsl:template name="xsl:initial-template">
<xsl:for-each select="uri-collection($uri)">
<xsl:message expand-text="yes">Processing file {.}</xsl:message>
<xsl:source-document href="{.}" streamable="yes">
<xsl:iterate select="outermost(descendant::country[@name = 'Country_Name'])">
<xsl:value-of select="."/>
<xsl:if test="position() eq $items-to-select">
<xsl:break/>
</xsl:if>
</xsl:iterate>
</xsl:source-document>
</xsl:for-each>
</xsl:template>
<xsl:output method="text" item-separator=" "/>
</xsl:stylesheet>
它通过了可流性分析,并且还指示提前退出(尽管当我处理三个文件(没有选项)时只有一次;如果我使用该选项并处理三个文件,则确实会退出三次:这是在 11.5 EE 中;我现在还使用 12.0 EE 进行了测试,它为每个处理的文件输出,而无需使用该选项)。-t
-t
SXQP0001 The input file has not been read to completion
-t
因此,这意味着,如果您的文件在所有或大量文档中该元素位于早期,则一旦找到该元素,就应该放弃该解析。
在一些简单的测试中,如果文件足够大,并且要查找的元素在每个文档的早期某个时间点,则通过 Saxon 12.0 EE 运行的流式、提前退出解决方案看起来比未流式处理的解决方案更快。
评论
xsl:iterate/xsl:break
xsl:iterate/xsl:break
通常,我建议人们流式处理不会使执行速度更快,其目的是减少内存使用。“提前退出”可能会有所作为,但只有测量才能说明问题。对于低于 100K 的文档,我相信相当多的 XML 解析成本是解析的初始化,因此提前退出可能不会像人们希望的那样节省那么多。
对于这种工作负载,使用 Saxon-EE 的最大收益可能来自输入文档的并行处理。Saxon-EE 下的函数会自动进行并行解析,但将其与流式处理相结合可能需要更多考虑。collection()
评论
xsl:for-each-stream select="doc('file:///C:/temp/*.xml')"