c# - 23 kB XML 文件的解析速度超过半秒
问题描述
我正在尝试基于 xmlreader 构建对象:
List<Element> units = new List<Element>();
string path = "D:\\Item\\Unit.xml";
XElement xelement = XElement.Load(path);
IEnumerable<XElement> elements = xelement.Elements();
foreach (var c in elements)
{
Element stb = new Element();
stb.Name = c.Element("Name").Value;
stb.Picture = c.Element("Picture").Value;
//and next 30 options included try / catch for int.Parse
}
XML:
<?xml version="1.0" encoding="UTF-8"?>
<rows>
<row id="1">
<Name>Freighter</Name>
<Picture>Item\Freighter.gif</Picture>
... and 30 next rows with data for each "unit"
</row>
... and 30 next units...
<rows>
正如我所说,XML 是 23kB 文件,每个单元有 30 行,文件中总共有 30 个单元。不知道为什么这段代码这么慢:花了 670 毫秒(i3 处理器)。最慢的部分是对象填充,但不知道如何改进它。
完整的代码看起来完全一样:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Diagnostics;
namespace element_reader
{
class Program
{
static void Main(string[] args)
{
CustomStopwatch sw = new CustomStopwatch();
sw.Start();
List<Element> ships = new List<Element>();
string path = "D:\\Ship_test.xml";
XElement xelement = XElement.Load(path);
IEnumerable<XElement> elements = xelement.Elements();
sw.Stop();
Console.WriteLine("Stopwatch elapsed: {0}, StartAt: {1}, EndAt: {2}", sw.ElapsedMilliseconds, sw.StartAt.Value, sw.EndAt.Value);
sw.Start();
foreach (var c in elements)
{
Element stb = new Element();
stb.Name = c.Element("Name").Value;
stb.Picture = c.Element("Picture").Value;
try
{
stb.Prt = int.Parse(c.Element("PRT").Value);
}
catch
{ stb.Prt = 0; }
try
{
stb.Lrt = int.Parse(c.Element("LRT").Value);
}
catch
{ stb.Lrt = 0; }
stb.Special = c.Element("Special").Value;
try
{
stb.Wep = int.Parse(c.Element("Wep").Value);
}
catch
{ stb.Wep = 0; }
try
{
stb.Con = int.Parse(c.Element("Con").Value);
}
catch
{ stb.Con = 0; }
try
{
stb.Ene = int.Parse(c.Element("Ene").Value);
}
catch
{ stb.Ene = 0; }
try
{
stb.Ele = int.Parse(c.Element("Ele").Value);
}
catch
{ stb.Ele = 0; }
try
{
stb.Prp = int.Parse(c.Element("Prp").Value);
}
catch
{ stb.Prp = 0; }
try
{
stb.Bio = int.Parse(c.Element("Bio").Value);
}
catch
{ stb.Bio = 0; }
try
{
stb.Mass = int.Parse(c.Element("Mass").Value);
}
catch
{ stb.Mass = 0; }
try
{
stb.Iro = int.Parse(c.Element("Iro").Value);
}
catch
{ stb.Iro = 0; }
try
{
stb.Bor = int.Parse(c.Element("Bor").Value);
}
catch
{ stb.Bor = 0; }
try
{
stb.Ger = int.Parse(c.Element("Ger").Value);
}
catch
{ stb.Ger = 0; }
try
{
stb.Res = int.Parse(c.Element("Res").Value);
}
catch
{ stb.Res = 0; }
ships.Add(stb);
}
sw.Stop();
Console.WriteLine("Stopwatch elapsed: {0}, StartAt: {1}, EndAt: {2}", sw.ElapsedMilliseconds, sw.StartAt.Value, sw.EndAt.Value);
Console.Read();
}
}
public class Element
{
public string Name;
public string Picture;
public int Prt;
public int Lrt;
public string Special;
public int Con;
public int Wep;
public int Ene;
public int Ele;
public int Prp;
public int Bio;
public int Mass;
public int Iro;
public int Bor;
public int Ger;
public int Res;
}
public class CustomStopwatch : Stopwatch
{
public DateTime? StartAt { get; private set; }
public DateTime? EndAt { get; private set; }
public void Start()
{
StartAt = DateTime.Now;
base.Start();
}
public void Stop()
{
EndAt = DateTime.Now;
base.Stop();
}
}
}
当 XML 的部分看起来完全一样时:
<?xml version="1.0" encoding="UTF-8"?>
<rows>
<row id="1">
<Name>Small Freighter</Name>
<Picture>Item\Ship\Ship01_1.gif</Picture>
<Description></Description>
<PRT></PRT>
<LRT></LRT>
<Special></Special>
<Ene>0</Ene>
<Wep>0</Wep>
<Prp>0</Prp>
<Con>0</Con>
<Ele>0</Ele>
<Bio>0</Bio>
<Slot1>-150, 0, Engine, 1, 1, 1</Slot1>
<Slot2>-50, 0, Cargo, 70, 1, 1</Slot2>
<Slot3>50, 0, DEF, 1, 1, 1</Slot3>
<Slot4>150, 0, SEM, 1, 1, 1</Slot4>
<Mass>25</Mass>
<Res>20</Res>
<Iro>12</Iro>
<Res>0</Res>
<Ger>17</Ger>
<Fuel>130</Fuel>
<Cargo>70</Cargo>
<HPD_arm>25</HPD_arm>
<Initiative>0</Initiative>
</row>
</rows>
1kB 文件的结果是 70 毫秒!!!如果我要加载 20 个文件,每个文件有 20-30 行,则此方法完全没用。请注意,我不使用文件中的所有数据。
解决方案
你没有提供完整xml
的文件内容,所以我只能建议你一件事。
使用int.TryParse
而不是int.Parse
. 我敢打赌,您的代码会引发数百个 CPU 非常昂贵的异常。
推荐阅读
- cookies - set-cookie 标头解码为单个字符数组
- google-apps-script - 检查幻灯片文本框的字符串相等性
- java - 编译DCEVM::hotspot:compileFastdebug系统找不到指定的路径
- visual-c++ - 在 CComboBoxEx 和 ReleaseBuffer 中插入和项目
- python - 将内部单引号切换为双引号,将外部双引号切换为字符串列表中的单引号
- c - 如何格式化 C 中所示的表格
- javascript - 使用 XMLHttpRequest() 检索数据后 DIV 不起作用
- docker - 如何将所有视频设备挂载到 docker 容器中?
- html - 将 & 放在 html 中的 href 属性中时,应该在 url 的参数键部分之前替换吗?
- apache-beam - Beam:并行处理多个侧面输入