2010-04-29 10 views
9

Tengo un archivo XML de 150 MB que se utiliza como base de datos en mi proyecto. Actualmente estoy usando XmlReader para leer su contenido. Quiero saber si es mejor usar XmlReader o LINQ a XML para este escenario.Rendimiento: XmlReader o LINQ a XML

Tenga en cuenta que estoy buscando un artículo en este XML y visualizo el resultado de la búsqueda, por lo que puede llevar mucho tiempo o solo un momento.

+1

Creo que está haciendo un mal uso de XML aquí. No lo use como db. 150 MB? : o Relacionado: http://stackoverflow.com/questions/1154499/linq-to-xml-vs-xmlreader – nawfal

Respuesta

2

escribir algunas pruebas de referencia para establecer con exactitud cuál es la situación para usted, y a partir de ahí ... Linq2XML introduce una gran flexibilidad ...

7

Me gustaría ver personalmente en utilizando LINQ to XML utilizando las técnicas de transmisión descritas en el archivo de ayuda de Microsoft: http://msdn.microsoft.com/en-us/library/system.xml.linq.xstreamingelement.aspx#Y1392

He aquí una prueba de referencia rápida lectura de un archivo XML 200mb con un filtro simple:

var xmlFilename = "test.xml"; 

//create test xml file 
var initMemoryUsage = GC.GetTotalMemory(true); 
var timer = System.Diagnostics.Stopwatch.StartNew(); 
var rand = new Random(); 
var testDoc = new XStreamingElement("root", //in order to stream xml output XStreamingElement needs to be used for all parent elements of collection so no XDocument 
    Enumerable.Range(1, 10000000).Select(idx => new XElement("child", new XAttribute("id", rand.Next(0, 1000)))) 
); 
testDoc.Save(xmlFilename); 
var outStat = String.Format("{0:f2} sec {1:n0} kb //linq to xml ouput streamed", timer.Elapsed.TotalSeconds, (GC.GetTotalMemory(false) - initMemoryUsage)/1024); 

//linq to xml not streamed 
initMemoryUsage = GC.GetTotalMemory(true); 
timer.Restart(); 
var col1 = XDocument.Load(xmlFilename).Root.Elements("child").Where(e => (int)e.Attribute("id") < 10).Select(e => (int)e.Attribute("id")).ToArray(); 
var stat1 = String.Format("{0:f2} sec {1:n0} kb //linq to xml input not streamed", timer.Elapsed.TotalSeconds, (GC.GetTotalMemory(false) - initMemoryUsage)/1024); 

//xmlreader 
initMemoryUsage = GC.GetTotalMemory(true); 
timer.Restart(); 
var col2 = new List<int>(); 
using (var reader = new XmlTextReader(xmlFilename)) 
{ 
    while (reader.ReadToFollowing("child")) 
    { 
     reader.MoveToAttribute("id"); 
     int value = Convert.ToInt32(reader.Value); 
     if (value < 10) 
      res2.Add(value); 
    } 
} 
var stat2 = String.Format("{0:f2} sec {1:n0} kb //xmlreader", timer.Elapsed.TotalSeconds, (GC.GetTotalMemory(false) - initMemoryUsage)/1024); 

//linq to xml streamed 
initMemoryUsage = GC.GetTotalMemory(true); 
timer.Restart(); 
var col3 = StreamElements(xmlFilename, "child").Where(e => (int)e.Attribute("id") < 10).Select(e => (int)e.Attribute("id")).ToArray(); 
var stat3 = String.Format("{0:f2} sec {1:n0} kb //linq to xml input streamed", timer.Elapsed.TotalSeconds, (GC.GetTotalMemory(false) - initMemoryUsage)/1024); 

//util method 
public static IEnumerable<XElement> StreamElements(string filename, string elementName) 
{ 
    using (var reader = XmlTextReader.Create(filename)) 
    { 
     while (reader.Name == elementName || reader.ReadToFollowing(elementName)) 
      yield return (XElement)XElement.ReadFrom(reader); 
    } 
} 

Y aquí es el tiempo de procesamiento y el uso de memoria en mi máquina:

11.49 sec 225 kb  // linq to xml ouput streamed 

17.36 sec 782,312 kb // linq to xml input not streamed 
6.52 sec 1,825 kb  // xmlreader 
11.74 sec 2,238 kb // linq to xml input streamed