代码之家  ›  专栏  ›  技术社区  ›  John Bustos

。Net-从系统中移动。Xml到Saxon。Api性能问题

  •  0
  • John Bustos  · 技术社区  · 7 年前

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

    我完成它的方式是使用 System.Xml.XmlReader 然后,当我到达需要从中收集值的最终节点时,我将这些非常小的元素转换为 System.Xml.Linq.XElement 并通过执行各种XPath语句 XEelement.XPathEvaluate 获取我需要的数据。

    这非常有效,但我遇到了一个问题,有时由于以下事实,我会得到错误的数据 XPathEvaluate 仅支持XPath 1.0,我的语句是XPath 2.0(已发布问题 here )。

    我最初执行此操作的代码如下所示:

    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 Saxon.Api (它确实支持XPath 2.0),我当前更新的代码如下所示:

    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)
        }
    }
    

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

    这是我第一次与撒克逊人合作。Api库,这就是我想到的。我希望有更好的方法来实现这一点,以使代码执行速度具有可比性,或者,如果有人对如何在不进行大量重写的情况下以更好的方式评估XPath 2.0语句有其他想法,我很乐意听到他们!

    任何帮助都将不胜感激!!

    谢谢

    更新时间:

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

    Processor processor = new Processor(false);
    XPathCompiler compiler = processor.NewXPathCompiler();
    

    相反,每次调用此方法都会不断地重新创建它们,这有很大的帮助,但过程仍然比本机慢3倍左右 System.Xml.Linq 版本关于实现这个解析器的方法,还有其他想法吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Michael Kay    7 年前

    这可能是您使用此设置所能做的最好的。

    撒克逊人。NET的速度通常是Java上Saxon的3-5倍,这是我们从未弄清的原因。我们目前正在探索使用Excelsior JET而不是IKVMC重建它的可能性,看看这是否可以加快速度。

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

    由于每次执行XPath表达式时都要对其进行解析,因此XPath编译时间可能会决定您的性能(即使您正在搜索大型XML文档)。直到最近,Saxon的编译时性能还很少受到关注,因为我们认为在编译时做更多的工作以节省运行时的工作量总是值得的;但在这种情况下,情况显然不是这样。可能有必要将编译时和运行时分开,并分别对两者进行测量,看看这是否能提供一些见解。例如,它可能建议关闭一些优化选项。显然,如果可以缓存和重用已编译的XPath表达式,这将有所帮助。