Best/Fastest 在 xml 文件中查找元素值的方法
Best/Fastest way to find values of a element in a xml file
我的程序主要做的是搜索 xml 和 returns 元素中具有特定值的文件名。
我想我必须先给你看我的xml才能继续:
<DocumentElement>
<Protocol>
<DateTime>10.03.2003</DateTime>
<Item>Date</Item>
<Value />
</Protocol>
<Protocol>
<DateTime>05.11.2020</DateTime>
<Item>Status</Item>
<Value>Ok</Value>
</Protocol>
</DocumentElement>
我有几千个 xml 具有这种布局的文件。用户可以使用以下方法获取所有文件的列表:
public List<string> GetFiles(string itemValue, string element, string value)
{
return compatibleFiles.Where(path => XmlHasValue(path, itemValue, element, value)).ToList();
}
并且此方法 returns 无论 xml 是否具有所需的值:
private bool XmlHasValue(string filePath, string itemValue, string element, string value)
{
try
{
string foundValue = XDocument.Load(filePath)
.Descendants()
.Where(el => el.Name == "Item" && el.Value == itemValue)
.First()
.Parent
.Descendants()
.Where(des => des.Name == element && des.Value == value)
.First()
.Value;
return foundValue == value;
}
catch (Exception)
{
return false;
}
}
compatibleFiles
是一个列表,其中包含 xml 文件的所有路径,这些文件具有正确的 layout/format(上面的 xml 代码)。用户提供 GetFiles
方法如下:
itemValue
-> 'Item' 元素应具有的值,例如“状态”
element
-> 他要检查的元素的名称(在同一个 'Protocol' 元素中),f.E。 “值”或“日期”
value
-> element
元素的值,在我们的示例中为“Ok”
问题是,这些方法需要很长时间才能完成,而且我几乎可以肯定有更好更快的方法来完成我想做的事情。我不知道 GetFiles
是否可以更快,但 XmlHasValue
肯定可以。以下是一些测试结果:
你们知道更快的方法吗?这真的很有帮助。
更新
原来都是IO线程的问题。如果你有同样的问题并认为你的代码不好,你应该首先检查它是否只是一个使用所有 cpu power 的线程。
正如@Sinatr 提到的那样。性能分析应该始终是调查性能的第一步。
关于什么需要时间的合理猜测是
- IO
- 正在解析
可以通过获得更快的磁盘或在 RAM 中缓存结果来改进 IO。如果进行多次搜索,后者可能会大大提高性能,但会引入 cache-invalidation.
等问题
根据“What is the best way to parse (big) XML in C# Code" XmlReader is the fastest way to parse xml. This blog suggest XmlReader is about 2.5 times faster.
如果您有多个文件,您也可以尝试并行处理多个文件。请记住,IO 主要是串行的,因此除非您拥有可以比文件处理速度更快地传输数据的 SSD,否则您可能什么也得不到。
我的程序主要做的是搜索 xml 和 returns 元素中具有特定值的文件名。
我想我必须先给你看我的xml才能继续:
<DocumentElement>
<Protocol>
<DateTime>10.03.2003</DateTime>
<Item>Date</Item>
<Value />
</Protocol>
<Protocol>
<DateTime>05.11.2020</DateTime>
<Item>Status</Item>
<Value>Ok</Value>
</Protocol>
</DocumentElement>
我有几千个 xml 具有这种布局的文件。用户可以使用以下方法获取所有文件的列表:
public List<string> GetFiles(string itemValue, string element, string value)
{
return compatibleFiles.Where(path => XmlHasValue(path, itemValue, element, value)).ToList();
}
并且此方法 returns 无论 xml 是否具有所需的值:
private bool XmlHasValue(string filePath, string itemValue, string element, string value)
{
try
{
string foundValue = XDocument.Load(filePath)
.Descendants()
.Where(el => el.Name == "Item" && el.Value == itemValue)
.First()
.Parent
.Descendants()
.Where(des => des.Name == element && des.Value == value)
.First()
.Value;
return foundValue == value;
}
catch (Exception)
{
return false;
}
}
compatibleFiles
是一个列表,其中包含 xml 文件的所有路径,这些文件具有正确的 layout/format(上面的 xml 代码)。用户提供 GetFiles
方法如下:
itemValue
-> 'Item' 元素应具有的值,例如“状态”element
-> 他要检查的元素的名称(在同一个 'Protocol' 元素中),f.E。 “值”或“日期”value
->element
元素的值,在我们的示例中为“Ok”
问题是,这些方法需要很长时间才能完成,而且我几乎可以肯定有更好更快的方法来完成我想做的事情。我不知道 GetFiles
是否可以更快,但 XmlHasValue
肯定可以。以下是一些测试结果:
你们知道更快的方法吗?这真的很有帮助。
更新
原来都是IO线程的问题。如果你有同样的问题并认为你的代码不好,你应该首先检查它是否只是一个使用所有 cpu power 的线程。
正如@Sinatr 提到的那样。性能分析应该始终是调查性能的第一步。
关于什么需要时间的合理猜测是
- IO
- 正在解析
可以通过获得更快的磁盘或在 RAM 中缓存结果来改进 IO。如果进行多次搜索,后者可能会大大提高性能,但会引入 cache-invalidation.
等问题根据“What is the best way to parse (big) XML in C# Code" XmlReader is the fastest way to parse xml. This blog suggest XmlReader is about 2.5 times faster.
如果您有多个文件,您也可以尝试并行处理多个文件。请记住,IO 主要是串行的,因此除非您拥有可以比文件处理速度更快地传输数据的 SSD,否则您可能什么也得不到。