.Net - 从System.Xml迁移到Saxon.Api性能问题

时间:2018-03-13 17:42:40

标签: c# xml xpath xml-parsing saxon

我编写了一个C#应用程序来解析非常大的(100MB +)XML文件。

我完成它的方式是我使用System.Xml.XmlReader遍历文件,然后,一旦我到达最终节点,我需要从中收集值,我将每个非常小的元素转换为{ {1}}并通过System.Xml.Linq.XElement执行各种XPath语句以获取我需要的数据。

这非常有效且效率很高,但由于XEelement.XPathEvaluate仅支持XPath 1.0而我的语句是XPath 2.0(问题发布为here},因此我有时会收到错误的数据。 )。

我最初这样做的代码看起来如下:

XPathEvaluate

根据我在上一个问题中提出的建议,我认为最好的解决方案是从void parseNode_Old(XmlReader rdr, List<string> xPathsToExtract) { // Enter the node: rdr.Read(); // Load it as an XElement so as to be able to evaluate XPaths: var nd = XElement.Load(rdr); // Loop through the XPaths related to that node and evaluate them: foreach (var xPath in xPathsToExtract) { var xPathVal = nd.XPathEvaluate(xPath); // Do whatever with the extracted value(s) } } 转移到System.Xml(它支持XPath 2.0),我当前更新的代码如下:< / p>

Saxon.Api

这是有效的(对我的XPath进行了一些其他更改),但速度变慢了大约5-10倍。

这是我第一次使用Saxon.Api库,这就是我想到的。我希望有更好的方法来实现这一目标,以使代码执行速度具有可比性,或者,如果有人对如何以更好的方式评估XPath 2.0语句有其他想法而没有大量的重写,I&I #39;我喜欢听他们!

非常感谢任何帮助!!

谢谢!

更新

在尝试自己解决这个问题时,我将以下两个语句移到了构造函数中:

void parseNode_Saxon(XmlReader rdr, List<string> xPathsToExtract)
{
    // Set up the Saxon XPath processors:
    Processor processor = new Processor(false);
    XPathCompiler compiler = processor.NewXPathCompiler();
    XdmNode nd = processor.NewDocumentBuilder().Build(rdr);

    // Loop through the XPaths related to that node and evaluate them:
    foreach (var xPath in xPathsToExtract)
    {
        var xPathVal = compiler.EvaluateSingle(xPath, (XdmNode)childNode);

        // Do whatever with the extracted value(s)
    }
}

而不是每次调用此方法时不断重新创建它们已经大大帮助了,但是该过程仍然比原生Processor processor = new Processor(false); XPathCompiler compiler = processor.NewXPathCompiler(); 版本慢大约3倍。关于如何实现此解析器的任何其他想法/想法?

1 个答案:

答案 0 :(得分:1)

这可能是您使用此设置所能做到的最佳效果。

Saxon on .NET的速度通常是Saxon在Java上慢3-5倍,原因我们从未深入到底。我们目前正在探索使用Excelsior JET而非IKVMC重建它的可能性,看看这是否可以加快速度。

Saxon在第三方DOM实现上比在其自己的本机树表示上慢得多,但似乎您已经更改了代码以使用本机树模型。

由于您每次执行时都要解析每个XPath表达式,因此您的性能可能会受XPath编译时间的影响(即使您正在搜索大型XML文档)。直到最近,Saxon的编译时性能很少受到关注,因为我们认为在编译时做更多工作以节省运行时的工作总是值得的;但在这种情况下,情况显然并非如此。可能值得拆分编译和运行时并单独测量,只是为了看看是否给出了任何见解。例如,它可能会建议关闭一些优化选项。显然,如果你可以缓存和重用已编译的XPath表达式,这将有所帮助。