XmlDocument vs XElement Performance

I have been using XElement class a lot lately, I was doing some performance tests on this to figure out the difference between this and XmlDocument class and here is what I found.

First of all XElement class is part of .NET Framework 3.5, it was introduced with XML to Linq and is part of System.Xml.Linq namespace. This class has been totally written from scratch to get better usability with LINQ. XElement.Nodes and XElement.Attribtues return IEnumerable which could be easily used to traverse nodes. You can also use them Lambda expressions. For more information on XML to LINQ check http://msdn.microsoft.com/en-us/library/bb387098.aspx.

In my case, I have created a test bench (console application) with two static methods, one uses XMLDocument and the other uses XElement to generate XML. The test case is very simple, iterate through the System assembly exported type, construct a giant XML and save it to a stream. Here is the code for both of the static methods.

    1: //Generates XML using XmlDocument
    2: internal static void GenerateXmlUsingXmlDocument() 
    3: {
    4:     MemoryStream ms =new MemoryStream();
    5:     XmlDocument xmlDoc = new XmlDocument();
    6:     xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", "no"));
    7:     XmlElement assembliesNode = xmlDoc.CreateElement("Assemblies");
    8:     foreach (Type t in Assembly.GetAssembly(typeof(Object)).GetExportedTypes())
    9:     {
   10:         XmlElement assemblyNode = xmlDoc.CreateElement("Assembly");
   11:         XmlAttribute fullTypeName = xmlDoc.CreateAttribute("FullTypeName");
   12:         fullTypeName.Value = t.ToString();
   13:         XmlAttribute isInterfaceName = xmlDoc.CreateAttribute("IsInterface");
   14:         isInterfaceName.Value = t.IsInterface.ToString();
   15:         assemblyNode.Attributes.Append(fullTypeName);
   16:         assemblyNode.Attributes.Append(isInterfaceName);
   17:         assembliesNode.AppendChild(assemblyNode);
   18:     }
   19:     xmlDoc.AppendChild(assembliesNode);
   20:     xmlDoc.WriteContentTo(new XmlTextWriter(ms,System.Text.ASCIIEncoding.ASCII));
   21: }
   22:  
   23: //Generates XML using XElement
   24: internal static void GenerateXmlUsingXElement()
   25: {
   26:     MemoryStream ms = new MemoryStream();
   27:     XElement assembliesNode = new XElement("Assemblies",
   28:             from Type t in Assembly.GetAssembly(typeof(Object)).GetExportedTypes()
   29:             select new XElement("Assembly",
   30:                 new XAttribute("FullTypeName", t.ToString()),
   31:                 new XAttribute("IsInterface", t.IsInterface.ToString())));
   32:     
   33:     assembliesNode.Save(new XmlTextWriter(ms, System.Text.ASCIIEncoding.ASCII));
   34: }

If you look at the above code, the XElement code is small and uses LINQ expressions for generating XML. By using the following code, I repeatedly test the amount of time it takes for each method to execute.

    1: Stopwatch sw = new Stopwatch();
    2: for (int index = 0; index < 51; index++)
    3: {
    4:     sw.Reset(); sw.Start();
    5:     Program.GenerateXmlUsingXmlDocument();
    6:     sw.Stop();
    7:     Console.Write("Generation time using XmlDocument " +
    8:         "and XElement: " + sw.ElapsedMilliseconds);
    9:     sw.Reset(); sw.Start();
   10:     Program.GenerateXmlUsingXElement();
   11:     sw.Stop();
   12:     Console.WriteLine(" : " + sw.ElapsedMilliseconds);
   13:     //Forcing the Garbage Collector to run to make sure,
   14:     //We dispose of all the types we created on the
   15:     //Managed heap.
   16:     GC.Collect();
   17: }
   18: Console.ReadKey();

From the above code, you can see that I am testing each method for 50 times. Additionally, after each test, I explicitly call Garbage Collector to clean up objects created by two methods. Now Here is the screen shot of the output.

XmlDocumentXElement

You can see very clearly, the huge difference in the time it takes to create XML. The difference seems to vary from 6x to 10x times. Specially, this is very important in ASP.NET applications and Web Services where every millisecond counts. One more thing to note that XElement is part of System.Xml.Linq.dll which is part of .NET Framework 3.5, but still uses .NET 2.0 CLR, thus technically you can use a local copy of System.Xml.Linq.dll within your application in cases where you are missing .NET 3.5. But, you will loose all goodness of updations and service packs by the .NET team.

Thanks

Anil RV