【问题标题】:Is XslCompiledTransform to blame for slow XML transformation for a large file?XslCompiledTransform 是否应归咎于大型文件的缓慢 XML 转换?
【发布时间】:2010-01-06 21:57:06
【问题描述】:

我是 XSLT 的新手,我需要做的第一件事是解析一个 300MB 的文件(这只是小端)。 XSLT 目前并不复杂,它只是删除了一些符合特定条件的节点。 我有两个问题:

  1. 太慢了。处理 500,000 条记录需要 50 秒,这还不够快。
  2. 它消耗 500MB 的内存,所以当文件变大时,这种情况只会变得更糟。

我可以在 .net 中本地做些什么来提高性能?

我知道我可以研究基于 SAX 的解析或 STX(在 another post 中提到),但我更愿意留在 .net 范围内。

谢谢!

编辑: 这是我的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http://schemas....">
 <xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
</xsl:template>
<xsl:template match="test:QueryRow[test:Columns/test:QueryColumn[test:Name='hit_count' and test:Value>200]]"/>
</xsl:stylesheet>

这是我用来进行转换的代码

XslCompiledTransform compiledTransform = new XslCompiledTransform();
XsltSettings settings = new XsltSettings();
settings.EnableScript = true;
XmlReader xmlReader = XmlReader.Create("in.xml");
XmlWriter xmlWriter = XmlWriter.Create("out.xml");
compiledTransform.Load("format.xslt", settings, null);
compiledTransform.Transform(xmlReader, xmlWriter); //this is what takes a long time

目前我正在尝试读取文件并将其写回,但它似乎实际上是将整个文件读入内存,所以我试图找到一种逐行读取它的方法。

【问题讨论】:

  • 另外,发布用于调用转换的代码。同时突出显示耗时 50 秒的代码行。
  • 需要多长时间 *) 读取源文件并 *) 使用 *) File.ReadAllBytes / WriteAllBytes 和 *) file.ReadAllText / WriteAllText 写入文件副本,以及执行时间会“足够快”吗?

标签: .net xml xslt parsing


【解决方案1】:

尝试分析您的 XSLT。 oXygen has a nice profiling capability 可以告诉您转换中的热点在哪里。

您可能有一些低效的 XPATH 表达式(例如 //*),或者将逻辑隐藏在模板中(例如,大量的 for-each、if、choose 等),这会阻止 XSLT 引擎进行优化。将其中一些逻辑上移到模板匹配条件中可以帮助引擎优化和减少您迭代和评估的节点集的大小。

【讨论】:

    【解决方案2】:

    您要过滤的 XPath 表达式本身没有任何明显错误。但很容易想象这是一个问题。如果您的QueryRow 元素都有20 个Column 子元素,每个子元素都有20 个QueryColumn 子元素,那么XSLT 处理器将不得不检查400 个元素,然后才能确定给定的QueryRow 元素不匹配。可以想象,这是非常低效的,因为如果事实证明该元素不应该被过滤,那么 XSLT 处理器必须再次访问所有 400 个元素以将它们全部输出。

    实现类似 SAX 的 XML 解析的 .NET 方法是将 XmlReader 子类化,在这种情况下您可以想象这样做:您基本上构建了一个 XmlReader 来缓冲 QueryRow 元素,因为它读取它们的后代直到它确定它们没问题,然后将它们返回给Read 方法的调用者。这将比使用 XSLT 过滤 XML 快得多,因为使用 XmlReader 不需要您在过滤之前构建未过滤 XML 文档的内存表示。

    【讨论】:

    • 这几乎就是我现在想要做的。缓冲每个查询行,然后对其进行过滤。
    【解决方案3】:

    您可以尝试查看Saxon,我听说它是​​一个非常优秀且高效的 XSLT 处理器。但是完整的 XSLT 不可能以流方式处理,即使您的转换听起来可能是这样,所以除非 XSLT 处理器非常擅长优化(据我所知,Saxon 是最好的之一,如果不是最好的) ),您的内存消耗问题可能无法解决。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-03
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      • 2017-08-14
      • 2012-10-14
      • 2011-11-27
      • 2019-01-15
      相关资源
      最近更新 更多