哪个性能最好:带XPath的XPathNavigator vs带查询的Linq to Xml?

哪个性能最好:带XPath的XPathNavigator vs带查询的Linq to Xml?

问题描述:

我有一个应用程序,使用XPathNavigator来迭代节点。它工作正常。哪个性能最好:带XPath的XPathNavigator vs带查询的Linq to Xml?

但我想知道,如果我使用LINQ到XML ....

  1. 什么好处(性能,可维护性),我会得到什么?

  2. 用XPath,LINQ to Xml是什么性能打击?

我使用C#.net,VS 2010和我的.xml是中等大小。

+0

你有没有考虑测量? – 2011-12-16 06:08:27

+0

@MitchWheat不,我需要将我的代码从XPathNavigator更改为LINQ到xml。所以在做这件事之前,我想知道它 – Syed 2011-12-16 06:11:52

那么,XPathNavigator通常会快于Linq to XML查询。但总是有'但'。

Linq to XML肯定会让你的代码更具可读性和可维护性。阅读linq查询然后分析XPath会更容易(至少对我来说)。另外 - 在写查询时你会得到智能感知,这将有助于使你的代码正确。 Linq to XML也为您提供了轻松修改数据的可能性,如果这是您的需要。 XPathNavigator为您提供只读访问权限。

另一方面,如果您确实需要顶级性能,XPathNavigator可能是最佳选择。它仅取决于您当前的场景以及您想要完成的内容。如果性能不是问题(XML文件相当小,您不会向这个文件发出很多请求等),您可以轻松地使用Linq to XML。否则坚持接近XPathNavigator

为了增加已经在此处陈述的内容,整体表现似乎取决于您对相关文档的实际操作。这是我基于一个简单的实验运行得出的结论,比较了XElement与XPathNavigator之间的解析性能。

如果您选择的节点,遍历这些节点和阅读一些属性值:

  • XElement.Element是1.5的 近似系数比XElement.CreateNavigator.Select更快。
  • XElement.CreateNavigator.Select比XPathNavigator更快 。选择近似系数0.5。
  • XPathNavigator.Select比XElement.XPathSelectElement快 约为0.5。

在另一方面,如果你还读每个节点的孩子们的价值就有点耐人寻味:

  • XElement.Element是0.5的近似系数比XElement.XPathSelectElements更快。
  • XElement.XPathSelectElement是由3
  • 近似因子XPathNavigator.Select是由0.5的近似因数大于XElement.CreateNavigator.Select速度比XPathNavigator.Select快。

这些结论是基于以下代码:

[Test] 
    public void CompareXPathNavigatorToXPathSelectElement() 
    {  
     var max = 100000; 

     Stopwatch watch = new Stopwatch(); 
     watch.Start(); 

     bool parseChildNodeValues = true; 

     ParseUsingXPathNavigatorSelect(max, watch, parseChildNodeValues); 
     ParseUsingXElementElements(watch, max, parseChildNodeValues); 
     ParseUsingXElementXPathSelect(watch, max, parseChildNodeValues); 
     ParseUsingXPathNavigatorFromXElement(watch, max, parseChildNodeValues); 
    } 

    private static void ParseUsingXPathNavigatorSelect(int max, Stopwatch watch, bool parseChildNodeValues) 
    { 
     var document = new XPathDocument(@"data\books.xml"); 
     var navigator = document.CreateNavigator(); 

     for (var i = 0; i < max; i++) 
     { 
      var books = navigator.Select("/catalog/book"); 
      while (books.MoveNext()) 
      { 
       var location = books.Current; 
       var book = new Book(); 
       book.Id = location.GetAttribute("id", ""); 

       if (!parseChildNodeValues) continue; 

       book.Title = location.SelectSingleNode("title").Value; 
       book.Genre = location.SelectSingleNode("genre").Value; 
       book.Price = location.SelectSingleNode("price").Value; 
       book.PublishDate = location.SelectSingleNode("publish_date").Value; 
       book.Author = location.SelectSingleNode("author").Value; 
      } 
     } 

     watch.Stop(); 
     Console.WriteLine("Time using XPathNavigator.Select = " + watch.ElapsedMilliseconds); 
    } 

    private static void ParseUsingXElementElements(Stopwatch watch, int max, bool parseChildNodeValues) 
    { 
     watch.Restart(); 
     var element = XElement.Load(@"data\books.xml"); 

     for (var i = 0; i < max; i++) 
     { 
      var books = element.Elements("book"); 
      foreach (var xElement in books) 
      { 
       var book = new Book(); 
       book.Id = xElement.Attribute("id").Value; 

       if (!parseChildNodeValues) continue; 

       book.Title = xElement.Element("title").Value; 
       book.Genre = xElement.Element("genre").Value; 
       book.Price = xElement.Element("price").Value; 
       book.PublishDate = xElement.Element("publish_date").Value; 
       book.Author = xElement.Element("author").Value; 
      } 
     } 

     watch.Stop(); 
     Console.WriteLine("Time using XElement.Elements = " + watch.ElapsedMilliseconds); 
    } 

    private static void ParseUsingXElementXPathSelect(Stopwatch watch, int max, bool parseChildNodeValues) 
    { 
     XElement element; 
     watch.Restart(); 
     element = XElement.Load(@"data\books.xml"); 

     for (var i = 0; i < max; i++) 
     { 
      var books = element.XPathSelectElements("book"); 
      foreach (var xElement in books) 
      { 
       var book = new Book(); 
       book.Id = xElement.Attribute("id").Value; 

       if (!parseChildNodeValues) continue; 

       book.Title = xElement.Element("title").Value; 
       book.Genre = xElement.Element("genre").Value; 
       book.Price = xElement.Element("price").Value; 
       book.PublishDate = xElement.Element("publish_date").Value; 
       book.Author = xElement.Element("author").Value; 
      } 
     } 

     watch.Stop(); 
     Console.WriteLine("Time using XElement.XpathSelectElement = " + watch.ElapsedMilliseconds); 
    } 

    private static void ParseUsingXPathNavigatorFromXElement(Stopwatch watch, int max, bool parseChildNodeValues) 
    { 
     XElement element; 
     watch.Restart(); 
     element = XElement.Load(@"data\books.xml"); 

     for (var i = 0; i < max; i++) 
     { 
      // now we can use an XPath expression 
      var books = element.CreateNavigator().Select("book"); 

      while (books.MoveNext()) 
      { 
       var location = books.Current; 
       var book = new Book(); 
       book.Id = location.GetAttribute("id", ""); 

       if (!parseChildNodeValues) continue; 

       book.Title = location.SelectSingleNode("title").Value; 
       book.Genre = location.SelectSingleNode("genre").Value; 
       book.Price = location.SelectSingleNode("price").Value; 
       book.PublishDate = location.SelectSingleNode("publish_date").Value; 
       book.Author = location.SelectSingleNode("author").Value; 
      } 
     } 

     watch.Stop(); 
     Console.WriteLine("Time using XElement.Createnavigator.Select = " + watch.ElapsedMilliseconds); 
    } 

用的books.xml从here

总体下载,它看起来像的XElement解析API,不包括XPath的扩展,使您最好的性能,同时也更容易使用,如果你的文档有点平淡。如果你有,你必须做一些像

XElement.Element("book").Element("author").Element("firstname").SomethingElse() 

深嵌套结构则XElement.XPathSelectElement可以提供性能和代码的可维护性之间的最佳平衡。