2010-04-29 6 views
9

J'ai un fichier XML de 150 Mo qui est utilisé comme base de données dans mon projet. Actuellement, j'utilise XmlReader pour en lire le contenu. Je veux savoir s'il est préférable d'utiliser XmlReader ou LINQ to XML pour ce scénario.Performances: XmlReader ou LINQ to XML

Notez que je suis à la recherche d'un élément dans ce fichier XML et affichez le résultat de la recherche, cela peut donc prendre beaucoup de temps ou juste un instant.

+1

Je pense que vous abusez XML ici. Ne l'utilisez pas comme un db. 150 Mo? : o Connexes: http://stackoverflow.com/questions/1154499/linq-to-xml-vs-xmlreader – nawfal

Répondre

8

Si vous voulez des performances, utilisez XMLReader. Il ne lit pas le fichier entier et ne construit pas l'arbre DOM en mémoire. Il lit à la place le fichier à partir du disque et vous rend chaque nœud qu'il trouve en chemin.

Avec une recherche google rapide, j'ai trouvé une comparaison des performances de XMLReader, LinqToXML et XDocument.Load.

https://web.archive.org/web/20130517114458/http://www.nearinfinity.com/blogs/joe_ferner/performance_linq_to_sql_vs.html

2

écrire quelques tests de référence pour établir exactement ce que la situation est pour vous, et à partir de là ... Linq2XML introduit beaucoup de flexibilité ...

7

je regarderais personnellement LINQ pour Xml en utilisant les techniques de diffusion en continu décrites dans le fichier d'aide Microsoft: http://msdn.microsoft.com/en-us/library/system.xml.linq.xstreamingelement.aspx#Y1392

est ici un test de référence rapide lecture d'un fichier xml 200mb avec un filtre 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); 
    } 
} 

Et voici le temps de traitement et de l'utilisation de la mémoire sur ma machine:

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