Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is the best for performance wise: XPathNavigator with XPath vs Linq to Xml with query?

I have an application in which I am using XPathNavigator to iterate nodes. It is working fine.

But I want to know that if I use LINQ to Xml....

  1. What benefits(Performance, maintainability) I will get?

  2. With XPath, LINQ to Xml what is the performance hit?

I am using C#.net, VS 2010 and my .xml is mid size.

like image 447
Syed Avatar asked Dec 16 '11 06:12

Syed


People also ask

What is xpath navigator?

An XPathNavigator object is created from a class that implements the IXPathNavigable interface such as the XPathDocument and XmlDocument classes. XPathNavigator objects created by XPathDocument objects are read-only while XPathNavigator objects created by XmlDocument objects can be edited.

What is LINQ to XML?

LINQ to XML is a LINQ-enabled, in-memory XML programming interface that enables you to work with XML from within the . NET programming languages. LINQ to XML is like the Document Object Model (DOM) in that it brings the XML document into memory.


2 Answers

Just to add onto what has already been stated here, overall performance seems to depends on what you are actually doing with the document in question. This is what I have concluded based on a simple experimental run comparing parsing performance between XElement to XPathNavigator.

If you are selecting nodes, traversing these nodes and reading some attribute values:

  • XElement.Element is faster than XElement.CreateNavigator.Select by an approximate factor of 1.5.
  • XElement.CreateNavigator.Select is faster than XPathNavigator.Select by an approximate factor of 0.5.
  • XPathNavigator.Select is faster than XElement.XPathSelectElement by an approximate factor of 0.5.

On the other hand, if you are also reading the value of each node's children it gets a little interesting:

  • XElement.Element is faster than XElement.XPathSelectElements by an approximate factor of 0.5.
  • XElement.XPathSelectElement is faster than XPathNavigator.Select by an approximate factor of 3.
  • XPathNavigator.Select is faster than XElement.CreateNavigator.Select by an approximate factor of 0.5.

These conclusions are based on the following code:

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

with books.xml downloaded from here

Overall, it looks like the XElement parsing API, excluding the XPath extensions, gives you the best performance, while also easier to use, if your document is somewhat flat. If you have deep nested structures where you have to do something like

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

then XElement.XPathSelectElement may provide the best compromise between performance and code maintainability.

like image 81
Klaus Nji Avatar answered Nov 14 '22 21:11

Klaus Nji


Well, XPathNavigator will generally be faster than Linq to XML queries. But there's always 'but'.

Linq to XML will definitely make your code more readable and maintainable. It's easier (at least for me) to read linq query then analyze XPath. Also - you will get intellisense when writing query which will help to make your code correct. Linq to XML also gives you possibility to easily modify data, if that's what you need. XPathNavigator gives you readonly access.

On the other hand, if you really need top performance, XPathNavigator is probably the way to go. It simply depends on your current scenario and what you're trying to accomplish. If performance is not an issue (XML file is rather small, you won't make many requests to this file and so on) you can easily go with Linq to XML. Otherwise stick close to XPathNavigator.

like image 20
Jarek Avatar answered Nov 14 '22 23:11

Jarek