LINQ to XML vs XPath的簡單效能測試
3 |
如果你使用的平台是.NET 3.5,在操作XML文件時會有三種選擇: LINQ to XML, LINQ to XML with XPath以及傳統的XmlDocument。既然有三種選擇,排除個人主觀偏好,想知道哪一種做法的效能最好呢?
之前有個迷思,一直覺得LINQ表達方式友善,理論上會付出效能上的代價(正所謂有一好沒兩好)。所以有時針對複雜的元素查詢,我會using System.Xml.XPath,然後改用XPathSelectElements()查詢,直到無意間發現了一篇談LINQ to XML與XPath Benchmark的文章,才發現我錯了。該文作者試了一個120,000筆資料, 54MB大小的XML檔案,LINQ to XML用LINQ語法查詢,竟比叫用XPathSelectElements()快了五倍!!
我自己也做了一個測試,產生一個36M大小20,000 * 100個Node的XML文件,分別用LINQ to XML, XPathSelectElements及XmlDocument.SelectNodes去查詢同樣條件,統計Node數。依我的測試結果,也驗證了LINQ to XML確實比XPathSelectElements來得快,至於XmlDocument,我們就忘了它吧...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
using System.Diagnostics;
using System.Xml.XPath;
using System.Xml;
namespace TestXmlPerformance
{
class Program
{
static void GenSampleXml()
{
StringBuilder sb = new StringBuilder();
sb.Append("<root>");
Random rnd = new Random();
for (int i = 0; i < 20000; i++)
{
sb.AppendFormat("<pack id=\"{0}\">", i);
for (int j = 0; j < 100; j++)
sb.AppendFormat("<item model=\"{0}\" />",
rnd.Next(20));
sb.Append("</pack>");
}
sb.Append("</root>");
File.WriteAllText(".\\Sample.xml", sb.ToString());
}
static void Main(string[] args)
{
//GenSampleXml();
{
Stopwatch sw = new Stopwatch();
sw.Start();
XDocument xd = XDocument.Load(".\\Sample.xml");
var q = from o in xd.Descendants("item")
where o.Attribute("model").Value == "7"
select o;
Console.WriteLine(q.Count());
sw.Stop();
Console.WriteLine("Test 1: {0}ms",
sw.ElapsedMilliseconds);
}
{
Stopwatch sw = new Stopwatch();
sw.Start();
XDocument xd = XDocument.Load(".\\Sample.xml");
Console.WriteLine(
xd.XPathSelectElements("root/pack/item[@model='7']")
.Count()
);
sw.Stop();
Console.WriteLine("Test 2: {0}ms",
sw.ElapsedMilliseconds);
}
{
Stopwatch sw = new Stopwatch();
sw.Start();
XmlDocument xd = new XmlDocument();
xd.Load(".\\Sample.xml");
Console.WriteLine(
xd.DocumentElement
.SelectNodes("pack/item[@model='7']").Count
);
sw.Stop();
Console.WriteLine("Test 3: {0}ms",
sw.ElapsedMilliseconds);
}
Console.Read();
}
}
}
【 測試數據 】
100507
Test 1: 3268ms
100507
Test 2: 3960ms
100507
Test 3: 9246ms
Comments
# by ina2588
感謝指導.可惜試了一下還是躲不開網路遠端xml讀取的gui延遲.backgroundWorker還是要用.
# by Ernest
黑大, 請教一下 如果想用ASP.NET + LINQ 運行一個SQL SP, 而該SP 一行就是10-15分鐘, 有可能不TIME OUT 嗎? 我可能怎樣做?
# by Jeffrey
to Ernest, DataContext有個CommandTimeout屬性(單位: 秒),把值加大應該就可以解決。http://msdn.microsoft.com/zh-tw/library/system.data.linq.datacontext.commandtimeout.aspx