2011-12-16 123 views
4

我有一個應用程序,使用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

回答

3

那麼,XPathNavigator通常會快於Linq to XML查詢。但總是有'但'。

Linq to XML肯定會讓你的代碼更具可讀性和可維護性。閱讀linq查詢然後分析XPath會更容易(至少對我來說)。另外 - 在寫查詢時你會得到智能感知,這將有助於使你的代碼正確。 Linq to XML也爲您提供了輕鬆修改數據的可能性,如果這是您的需要。 XPathNavigator爲您提供只讀訪問權限。

另一方面,如果您確實需要頂級性能,XPathNavigator可能是最佳選擇。它僅取決於您當前的場景以及您想要完成的內容。如果性能不是問題(XML文件相當小,您不會向這個文件發出很多請求等),您可以輕鬆地使用Linq to XML。否則堅持接近XPathNavigator

5

爲了增加已經在此處陳述的內容,整體表現似乎取決於您對相關文檔的實際操作。這是我基於一個簡單的實驗運行得出的結論,比較了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可以提供性能和代碼的可維護性之間的最佳平衡。