2010-04-29 40 views
9

Tôi có một tệp XML 150 MB được sử dụng làm DB trong dự án của tôi. Hiện tại tôi đang sử dụng XmlReader để đọc nội dung từ đó. Tôi muốn biết nếu nó là tốt hơn để sử dụng XmlReader hoặc LINQ to XML cho kịch bản này.Hiệu suất: XmlReader hoặc LINQ to XML

Lưu ý rằng tôi đang tìm kiếm một mục trong XML này và hiển thị kết quả tìm kiếm, vì vậy có thể mất một thời gian dài hoặc chỉ một lát.

+1

Tôi nghĩ rằng bạn đang lạm dụng XML ở đây. Không sử dụng nó như một db. 150 MB? : o Liên quan: http://stackoverflow.com/questions/1154499/linq-to-xml-vs-xmlreader – nawfal

Trả lời

8

Nếu bạn muốn sử dụng hiệu suất XMLReader. Nó không đọc toàn bộ tệp và xây dựng cây DOM trong bộ nhớ. Thay vào đó, đọc tệp từ đĩa và cung cấp cho bạn lại mỗi nút mà nó tìm thấy trên đường.

Với tìm kiếm nhanh trên google, tôi đã tìm thấy một so sánh hiệu suất của XMLReader, LinqToXML và XDocument.Load.

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

2

Viết một vài bài kiểm tra điểm chuẩn để thiết lập chính xác những gì tình hình là dành cho bạn, và mang nó từ đó ... Linq2XML giới thiệu rất nhiều tính linh hoạt ...

7

Cá nhân tôi sẽ xem xét sử dụng LINQ to XML sử dụng các kỹ thuật trực tuyến được nêu trong Microsoft tập tin trợ giúp: http://msdn.microsoft.com/en-us/library/system.xml.linq.xstreamingelement.aspx#Y1392

Dưới đây là một thử nghiệm benchmark nhanh chóng đọc từ một tập tin 200MB xml với một bộ lọc đơn giản:

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

Và đây là thời gian xử lý và sử dụng bộ nhớ trên máy tính của tôi:

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