2010-04-29 1 views
9

Ho un file XML da 150 MB che viene utilizzato come DB nel mio progetto. Attualmente sto usando XmlReader per leggere il contenuto da esso. Voglio sapere se è meglio usare XmlReader o LINQ in XML per questo scenario.Prestazioni: XmlReader o LINQ to XML

Nota che sto cercando un elemento in questo XML e visualizzo i risultati di ricerca, quindi può richiedere molto tempo o solo un momento.

+1

Penso che si sta abusando XML qui. Non usarlo come db. 150 MB? : o correlati: http://stackoverflow.com/questions/1154499/linq-to-xml-vs-xmlreader – nawfal

risposta

2

scrivere qualche test di benchmark per stabilire esattamente qual è la situazione per voi, e prendere da lì ... Linq2XML introduce un sacco di flessibilità ...

7

Io personalmente guardare utilizzando LINQ to XML utilizzando le tecniche di streaming delineate nel file di aiuto Microsoft: http://msdn.microsoft.com/en-us/library/system.xml.linq.xstreamingelement.aspx#Y1392

Ecco un test di benchmark rapida lettura da un file di 200MB XML con un semplice filtro:

0.123.516,410617 millions
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); 
    } 
} 

Ed ecco il tempo di elaborazione e della memoria sulla mia macchina:

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