C# 如何加快大型xml文件的读/写操作

C# 如何加快大型xml文件的读/写操作,c#,xml,parallel-processing,C#,Xml,Parallel Processing,我有一个windows窗体应用程序,当前执行以下操作: 1) 指向一个目录,对其中的所有xml文件执行2)操作(通常最多25个文件,范围从10mb到!5gb!-不常见但可能) 2) xml读/写来改变一些现有的xml属性(目前我只使用一个后台工作程序) 3) 将修改后的xml属性直接写入另一目录中的新文件 这个小应用程序工作正常,但需要很长时间才能完成(大约20分钟,取决于净gb大小) 我偶然尝试的是在Parallel.ForEach()中启动主rw方法,但它不出所料地将自己屏蔽并退出 我的想法

我有一个windows窗体应用程序,当前执行以下操作:

1) 指向一个目录,对其中的所有xml文件执行2)操作(通常最多25个文件,范围从10mb到!5gb!-不常见但可能)

2) xml读/写来改变一些现有的xml属性(目前我只使用一个后台工作程序)

3) 将修改后的xml属性直接写入另一目录中的新文件

这个小应用程序工作正常,但需要很长时间才能完成(大约20分钟,取决于净gb大小) 我偶然尝试的是在Parallel.ForEach()中启动主rw方法,但它不出所料地将自己屏蔽并退出

我的想法是通过同时在所有25个文件上启动读/写过程来并行化读/写过程,这样明智吗?我怎样才能不把自己锁在外面就做到这一点(第三方物流?)


PS:我有一台功能相当强大的台式电脑,配有1TB三星pro ssd、16gb ram和intel core i7,您可以使用线程池来实现这种方法

您可以有一个大小为20个文件的池 因为您有core i7,所以应该使用TaskFactory.StartNew 在这种情况下,您应该将用于文件处理的代码封装在一个示例类(如XMLProcessor)中
然后通过使用TaskFactory.StartNew,您可以将多线程用于xml处理

这听起来像是通过PLINQ+异步lambda实现数据并行的工作

我最近需要处理一个zip档案中的数据,该档案本身包含5200个zip档案,每个zip档案都包含一个或多个XML或CSV格式的数据文件。总的来说,解压并读入内存时,数据容量在40-60 GB之间

该算法浏览这些数据,根据找到的数据和提供的谓词做出决策,最后将选择作为1.0-1.5 GB文件写入磁盘。使用具有32个处理器的异步PLINQ模式,每个输出文件的平均运行时间为4.23分钟

在使用async PLINQ实现了直截了当的解决方案之后,我花了一些时间试图通过深入研究TPL和TPL数据流库来提高运行时间。最后,尝试击败async PLINQ被证明是一个有趣的,但最终对我的需求毫无结果的练习。更“优化”的解决方案带来的性能优势不值得增加复杂性

下面是异步PLINQ模式的示例。初始集合是一个文件路径数组

在第一步中,将每个文件路径异步读取到内存中并进行解析,将文件名缓存为根级别属性,并流式传输到下一个函数

在最后一步中,将每个
XElement
异步写入一个新文件

我建议您使用读取文件的lambda。在我的例子中,我发现通过异步lambda进行读取可以在解压缩内存中的文件时提供更好的吞吐量

但是,对于简单的XML文档,最好用对
XElement.Load(string file)
的方法调用替换第一个异步lambda,并让PLINQ根据需要读取

使用System.IO;
使用System.Linq;
使用System.Xml.Linq;
命名空间异步示例
{
公共课程
{
公共静态void Main(字符串[]args)
{
//如果需要,在此处限制并行性
int degreeOfParallelism=Environment.ProcessorCount;
字符串resultDirectory=“[result directory path here]”;
string[]files=Directory.GetFiles(“[Directory with files here]”);
files.AsParallel()文件
.带平行度(平行度)
.选择(
异步x=>
{
使用(StreamReader=新StreamReader(x))
{
XElement root=XElement.Parse(wait reader.ReadToEndAsync());
SetAttributeValue(“filePath”,Path.GetFileName(x));
返回根;
}
})
.选择(x=>x.Result)
.选择(
x=>
{
//在这里执行其他操作
返回x;
})
.选择(
异步x=>
{
字符串结果路径=
路径。联合收割机(
结果目录,
(字符串)x.Attribute(“文件名”);
wait Console.Out.WriteLineAsync($“{DateTime.Now}:启动{(string)x.Attribute(“fileName”)}”);
使用(StreamWriter writer=新StreamWriter(resultPath))
{
等待WriteAsync(x.ToString());
}
wait Console.Out.WriteLineAsync($“{DateTime.Now}:Comleted{(string)x.Attribute(“fileName”)}”);
});
}
}
}

我很惊讶它自己被锁在外面了!你确定使用XML数据库不是更好的解决方案吗?我把你的意见放在心上,研究了XML数据库,我之前对这些数据库一无所知,所以这可能是一个选择……感谢你分享你在该主题上的经验,我目前无法回到这个话题,但我将能够在下周,希望我能采纳其中一些建议,并尽快向大家汇报