几种xml读取方法比较
背景
这几天手上有个活,解析xml,众所周知xml的解析方法有:
- DOM
- SAX
- linq to xml
- plinq
测试用xml和生成代码
1 static void CreateFile() 2 { 3 int N = 5000000; 4 Random rand = new Random(); 5 using (var writer = new XmlTextWriter("VeryHugeXmlFile.xml", Encoding.UTF8)) 6 { 7 writer.Formatting = Formatting.Indented; 8 9 writer.WriteStartDocument(); 10 writer.WriteStartElement("Root"); 11 for (int count = 1; count <= N; count++) 12 { 13 writer.WriteStartElement("Person"); 14 writer.WriteElementString("Id", count.ToString()); 15 writer.WriteElementString("Name", rand.Next().ToString()); 16 writer.WriteElementString("Sex", rand.Next(0, 2) == 0 ? "男" : "女"); 17 writer.WriteElementString("Age", rand.Next(1, 101).ToString()); 18 writer.WriteEndElement(); 19 } 20 writer.WriteEndElement(); 21 writer.WriteEndDocument(); 22 } 23 }
之后会生成类似于下面的xml文件
1 <?xml version="1.0" encoding="utf-8"?> 2 <Root> 3 <Person> 4 <Id>1</Id> 5 <Name>897639886</Name> 6 <Sex>女</Sex> 7 <Age>80</Age> 8 </Person> 9 <Person> 10 <Id>2</Id> 11 <Name>2012162696</Name> 12 <Sex>女</Sex> 13 <Age>60</Age> 14 </Person> 15 <Person>
测试代码
统计时间(只是粗略统计了一下运行时间)
1 static void Watch(Action<string> way, string file) 2 { 3 Stopwatch watch = new Stopwatch(); 4 5 watch.Start(); 6 way(file); 7 watch.Stop(); 8 Console.WriteLine(watch.ElapsedMilliseconds); 9 }
DOM
1 static void DomWay(string file) 2 { 3 XmlDocument doc = new XmlDocument(); 4 doc.Load(file); 5 6 Console.WriteLine(doc.SelectNodes(YOUR-XPATH-HERE).Count); 7 8 }
SAX
1 static void SaxWay(string file) 2 { 3 using (XmlTextReader reader = new XmlTextReader(file)) 4 { 5 int count = 0; 6 while (reader.Read()) 7 { 8 if (reader.Name == "Person" && reader.NodeType == XmlNodeType.Element) 9 { 10 reader.Read(); 11 reader.Read(); 12 13 int? Id = null; 14 int? name = null; 15 string sex = null; 16 int? age = null; 17 18 if (reader.Name == "Id") 19 { 20 Id = reader.ReadElementContentAsInt(); 21 reader.Read(); 22 name = reader.ReadElementContentAsInt(); 23 reader.Read(); 24 sex = reader.ReadElementContentAsString(); 25 reader.Read(); 26 age = reader.ReadElementContentAsInt(); 27 reader.Read(); 28 } 29 30 if (reader.Name == "Person" && reader.NodeType == XmlNodeType.EndElement) 31 reader.Read(); 32 33 if (Id != null && name != null && sex != null && age != null) 34 { 35 if (在此设置自定义过滤条件) 36 count++; 37 } 38 } 39 } 40 41 Console.WriteLine(count); 42 } 43 }
Linq to Xml
1 static void LinqWay(string file) 2 { 3 var root = XElement.Load(file); 4 var person = from p in root.Elements("Person")
7 where 在此设置自定义过滤条件
8 select id; 9 Console.WriteLine(person.Count()); 10 }
PLinq to Xml
1 static void PLinqWay(string file) 2 { 3 var root = XElement.Load(file); 4 var person = from p in root.Elements("Person").AsParallel()
7 where 在此设置自定义过滤条件
8 select id; 9 Console.WriteLine(person.Count()); 10 }
统计结果
在6核8G内存机器上,测试程序设置为x64和release模式,在xml查询结果相同的情况下取运行时间(ms),没有详细采集cpu和内存数据
两个模式,区别是加了一个素数的判断。
Id > 5000 && sex == "男" && age > 15 && age < 50 |
Id > 5000 && sex == "男" && age > 15 && age < 50 && IsPrimeInt(name) |
|
sax | 13857 | 40010 |
linq | 27336 | 53760 |
plinq | 24550 | 28846 |
dom | 31737 | 0 |
由于dom模式本身xpath模式不支持嵌入函数,所以第二个测试没有采集结果。
小结
sax:速度优先,内存占用少,但是代码复杂度高。
linq:速度较sax慢,但是代码优雅,维护容易
plinq:同上,在非计算密集型模式中,不比linq和sax模式好多少。但是在计算密集下,后来居上
dom:速度落后,但是原生支持xpath,代码最优雅。
内存方面仅是肉眼观察了任务管理器,sax基本内存曲线为水平线,而linq&plinq在load的时候分配内存,可能其内部也是用了dom。
仓促行文,其中必有不实之处,往各位劳神指教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义