C# 如何改进我在硬盘上存储数据的算法?
我想处理太多的文本数据,然后将其保存到zip存档的硬盘上。由于处理应该以多线程方式进行,因此任务变得复杂C# 如何改进我在硬盘上存储数据的算法?,c#,.net,multithreading,algorithm,zip,C#,.net,Multithreading,Algorithm,Zip,我想处理太多的文本数据,然后将其保存到zip存档的硬盘上。由于处理应该以多线程方式进行,因此任务变得复杂 ... ZipSaver saver = new ZipSaver(10000); // 10000 - is the number of items when necessary to save the file to hard drive Parallel.ForEach(source, item => { string workResult = ModifyItem(it
...
ZipSaver saver = new ZipSaver(10000); // 10000 - is the number of items when necessary to save the file to hard drive
Parallel.ForEach(source, item => {
string workResult = ModifyItem(item);
saver.AddItem(workResult);
});
ZipSaver类的一部分(使用库Ionic ZipFile)
专用ConcurrentQueue\u池;
公共void附加项(字符串src){
ZipFile电流ZipFile;
if(_pool.TryDequeue(out currentZipFile)==false){
currentZipFile=InitNewZipFile();//
}
currentZipFile.AddEntry(path,src);//如果池不可用,请创建一个新的存档
//如果将项目添加到存档后,您已达到最大元素数,
//在构造函数中指定,将此文件保存到硬盘,
//否则,将归档文件返回到公共池中
如果(currentZipFile.Enties.Count>\u maxEntries){
SaveZip(currentZipFile);
}否则{
_pool.Enqueue(currentZipFile);
}
}
当然,我可以使用归档文件中的最大项数,但这取决于输出文件的大小,理想情况下,应该配置输出文件的大小。现在,许多集合项在循环中被处理,创建了许多线程,这些线程都很实用,每个线程都有其“自己的”实例ZipFile,这会导致RAM溢出。
如何完善保护机制?对不起,我的英语=)限制并发线程的数量怎么样,这将限制队列中的
ZipFile
实例的数量。例如:
Parallel.ForEach(source,
new ParallelOptions { MaxDegreeOfParallelism = 3 },
item =>
{
string workResult = ModifyItem(item);
saver.AddItem(workResult);
});
也可能是10000件物品太多了。如果要添加的文件的大小都是1兆字节,那么其中10000个文件将创建一个10千兆字节的文件。这可能会使你的内存耗尽
您需要按大小而不是文件数量限制zip文件。我不知道DotNetZip是否会让您看到输出缓冲区中当前有多少字节。如果没有其他方法,您可以估计压缩比,并通过计算未压缩字节数来限制大小。也就是说,如果您期望50%的压缩率,并且希望将输出文件大小限制为1GB,则需要将总输入限制为2GB(即1GB/0.5=2GB
)
如果您能看到当前的输出大小,这将是最好的。我不熟悉DotNetZip,所以我不能说它是否具有这种功能。这几乎可以肯定是I/O绑定的;添加额外的线程实际上可能会减慢速度。您应该先做一些性能测量,看看您是否已经用一个线程在硬盘上达到了最大可能的吞吐量。@RobertHarvey唯一并行完成的事情是
ModifyItem
,这似乎是CPU限制的工作。正如人们所希望的,所有IO(显示的)都已序列化。@Servy:如果他是I/O绑定的,我的注释仍然适用(除了“减速”部分),而不管哪个部分正在并行化。任何试图在I/O绑定操作上并行CPU工作的尝试几乎肯定不会产生任何改进。关于池的组织而不是关于保存到硬盘驱动器的问题您是否分析了代码以确定队列中有多少不同的ZipFile实例?你知道在任何时候有多少线程正在运行吗?似乎您可以很容易地限制并行度,以确保并发运行的线程不超过3或4个,这可能很好地解决了您的问题。谢谢您的回答!不幸的是,DotNetZip无法获得当前的输出大小。您的变体确实可以解决问题,但我担心它会影响整个程序的性能。例如,如果在源代码中有10000个项目,现在它在“最大速度”中工作正常,但在1000000(RAM问题)中工作不好。如果我将限制100个线程(例如),我将解决我的RAM问题,但不是“最大速度”。。。但是,您的答案是最好的=)
Parallel.ForEach(source,
new ParallelOptions { MaxDegreeOfParallelism = 3 },
item =>
{
string workResult = ModifyItem(item);
saver.AddItem(workResult);
});