对多个文件副本使用多线程

本文关键字:多线程 副本 文件 | 更新日期: 2023-09-27 18:28:00

我必须复制大量文件(10000个文件)

因为复制需要很长时间。我尝试使用两个线程而不是单个线程,一个用于复制列表中的奇数文件,另一个用于从列表复制偶数

我用过这个代码:

ThreadPool.QueueUserWorkItem(new WaitCallback(this.RunFileCopy),object)

但是当使用单个线程时和当使用两个线程时在时间上没有显著差异。

这可能是什么原因?

对多个文件副本使用多线程

文件复制不是CPU进程,而是IO进程,因此多线程或并行性对您没有帮助。

几乎在所有情况下,多线程都会减慢速度。如果光盘也是SSD,它的r/w速度有限,而且它也可以通过单线程有效地使用它。如果你使用并行,你只会把你的速度分成几块,这将给HDD带来巨大的开销

多线程只能在多个光盘盒中帮助您,当您从不同的光盘读取并写入不同的光盘时。

如果文件太小。在大多数情况下,压缩和解压缩目标驱动器上的文件会更快,如果你用低压缩率压缩文件,会更快

using System.IO;
using System.IO.Compression;
.....
string startPath = @"c:'example'start";
string zipPath = @"c:'example'result.zip";
string extractPath = @"c:'example'extract";
ZipFile.CreateFromDirectory(startPath, zipPath, CompressionLevel.Fastest, true);
ZipFile.ExtractToDirectory(zipPath, extractPath);

点击此处了解更多实施细节

如何:压缩和提取文件

我将在这里提供少数人的意见。每个人都在告诉你,磁盘I/O正在阻止你从多个线程获得任何加速。那是。。。分类当然,但是。。。

给定一个磁盘请求,操作系统只能选择将磁头移动到文件访问所选磁盘上的点,通常会导致访问数据的全行程寻道时间(数十毫秒)和旋转延迟(另外10毫秒)的平均一半。坚持使用单磁盘请求,这是一个非常可怕(也是不可避免的)的代价。

由于磁盘访问需要很长时间,操作系统有足够的CPU来考虑在有多个请求时访问磁盘的最佳顺序,如果这些请求发生在它已经在等待磁盘执行某些操作的时候。操作系统通常使用升降算法,使磁头在一次通过中沿一个方向高效地扫描磁盘,并在达到"最远"访问时沿另一个方向有效地扫描。

这个想法很简单:如果你按照多个磁盘请求发生的时间顺序处理它们,那么磁盘头可能会在磁盘上随机跳跃(假设文件是随机放置的),从而在每次访问时产生helf全寻道+旋转延迟。按顺序处理1000个实时访问后,将出现1000个平均半满寻道。Ick。

相反,给N个几乎同时的访问,操作系统可以根据它们将要接触的物理圆柱体对这些访问进行排序,然后按圆柱体顺序处理它们。1000个实时访问,按柱面顺序处理(即使是随机文件分发),每个柱面可能有一个请求。现在,磁头只需要从一个气缸走到下一个气缸,这比平均寻道要少得多。

因此,拥有大量请求应该有助于操作系统做出更好的访问顺序决策。

由于OP有很多文件,所以他没有理由不运行很多线程,每个线程都复制自己的文件并产生对磁盘位置的需求。他希望每个线程都能发出一个类似于完整磁道的读写操作,这样当磁头到达一个柱面时,就会读取或写入一个完整磁道(假设操作系统将文件连续地放在一个磁道上)。

OP希望确保他的机器有足够的RAM来缓冲线程数乘以轨迹大小。在复制过程中具有4 Gb未绑定的8Gb机器基本上具有4 Gb磁盘缓存。每首曲目100Kb(我已经很久没有看了)表明有10000个线程的"空间"。我很怀疑他需要那么多;大多数情况下,他需要足够的线程来淹没磁盘上的柱面数量。我肯定会考虑几百条线索。

两条线肯定是不够的。(当你要求Windows复制一堆文件时,它似乎使用了一个线程。这对我来说总是很愚蠢)。

另一张海报建议将文件压缩。由于有很多线程,所有的东西都在磁盘上等待(电梯算法不会改变这一点,只会改变平均等待时间),许多线程可以在压缩时抛出计算周期。这对阅读没有帮助;文件就是读取时的样子。但它可能会缩短要写入的数据量,并在内存中提供更大的缓冲区,从而提供一些额外的加速。

注意:如果有SSD,那么就没有物理圆柱体,因此没有寻道时间,也没有电梯算法可以优化的东西。在这里,大量螺纹不会为气缸订购时间带来任何好处。他们也不应该受伤。