提高高速文件复制的写入速度?

时间:2010-01-08 05:22:12

标签: c++ windows copy raid

我一直在努力寻找编写文件复制例程的最快方法,将大文件复制到RAID 5硬件上。

平均文件大小约为2 GB。

有2个窗口框(都运行win2k3)。第一个框是源,大文件位于何处。第二个盒子有一个RAID 5存储空间。

http://blogs.technet.com/askperf/archive/2007/05/08/slow-large-file-copy-issues.aspx

以上链接清楚地解释了为什么Windows复制,robocopy和其他常见复制实用程序在写入性能方面受到影响。 因此,我编写了一个使用CreateFile,ReadFile& S的C / C ++程序。 WriteFile API与NO_BUFFERING& WRITE_THROUGH个标志。该程序模拟ESEUTIL.exe,从某种意义上说,它使用2个线程,一个用于读取,一个用于写入。读取器线程从源读取256 KB并填充缓冲区。一旦填充了16个这样的256 KB块,写入器线程就会将缓冲区中的内容写入目标文件。如您所见,编写器线程在一次写入中写入8MB的数据。该程序分配32个这样的8MB块...因此,写入和读取可以并行发生。 可以在上面的链接中找到ESEUtil.exe的详细信息。 注意:使用NO_BUFFERING时,我正在处理数据对齐问题。

我使用像ATTO这样的基准测试工具,发现我们的RAID 5硬件在写入8MB数据块时的写入速度为每秒44MB。其中每分钟2.57 GB

但我的程序每分钟只能 1.4 GB。

任何人都可以帮我确定问题所在吗?是否有更快的API,CreateFileReadFileWriteFile可用吗?

7 个答案:

答案 0 :(得分:6)

您应该使用异步IO来获得最佳性能。这是使用FILE_FLAG_OVERLAPPED打开文件并使用WriteFile的LPOVERLAPPED参数。使用FILE_FLAG_NO_BUFFERING可能会或可能不会获得更好的效果。你将不得不测试看看。

FILE_FLAG_NO_BUFFERING通常会为您提供更加一致的速度和更好的流式传输行为,并且它可以避免使用您可能不再需要的数据来污染您的磁盘缓存,但总体而言不一定更快。

您还应该测试以查看每个IO块的最佳大小。根据我的经验,一次复制4k文件和一次复制1Mb文件之间存在巨大的性能差异。

在我过去对此(几年前)的测试中,我发现大小低于64kB的块大小由开销占主导地位,并且总吞吐量继续提高,块大小增加到大约512KB。如果使用今天的驱动器,您需要使用大于1MB的块大小来获得最大吞吐量,我不会感到惊讶。

您当前使用的数字似乎合理,但可能不是最佳数字。另外我很确定FILE_FLAG_WRITE_THROUGH可以防止使用磁盘缓存,因此会花费你相当多的性能。

您还需要注意,使用CreateFile / WriteFile复制文件不会在NTFS上复制时间戳或备用数据流等元数据。你必须自己处理这些事情。

实际上用自己的代码替换CopyFile是非常多的工作。

附录:

我应该提一下,当我在WindowsNT 3.0(大约10年前)上使用软件Raid 0进行尝试时。速度对缓冲区内存的对齐非常敏感。事实证明,当DMA超过16个物理内存区域(64Kb)时,SCSI驱动程序必须使用特殊算法从分散/收集列表中执行DMA。要获得保证的最佳性能,需要物理上连续的分配 - 这是只有驱动程序才能请求的。这基本上是当时流行芯片组的DMA控制器中的一个错误的解决方法,并且不太可能仍然是一个问题。

但是 - 我仍然强烈建议您测试2块大小的所有功率,从32kb到32Mb,看看哪个更快。你可能会考虑测试一下缓冲区是否总是比其他缓冲区更快 - 这并不是闻所未闻的。

答案 1 :(得分:2)

前段时间我写了一篇关于异步文件I / O的博客文章,以及除非你做的一切都恰到好处(http://www.lenholgate.com/blog/2008/02/when-are-asynchronous-file-writes-not-asynchronous.html),否则它往往会最终实现同步。

关键点是,即使您使用FILE_FLAG_OVERLAPPEDFILE_FLAG_NO_BUFFERING,仍需要预先扩展文件,以便异步写入不需要扩展文件;出于安全原因,文件扩展名始终是同步的要预先扩展,您需要执行以下操作:

  • 启用SE_MANAGE_VOLUME_NAME权限。
  • 打开文件。
  • 使用SetFilePointerEx()寻找所需的文件长度。
  • 使用SetEndOfFile()设置文件结尾。
  • 在文件SetFileValidData()中设置有效数据的结尾。
  • 关闭文件。

则...

  • 打开要写的文件。
  • 发出写入

答案 2 :(得分:0)

如果您没有写目的地,您可以多快读取源文件?

源文件是否碎片化?碎片读取比连续读取慢一个数量级。您可以使用“contig”实用程序使其连续:

http://technet.microsoft.com/en-us/sysinternals/bb897428.aspx

连接这两台机器的网络有多快?

您是否尝试过编写虚拟数据,而不是像ATTO那样先读取它?

您一次在飞行中有多个读写请求吗?

RAID-5阵列的条带大小是多少?一次写一个完整的条带是写入RAID-5的最快方法。

答案 3 :(得分:0)

请记住,硬盘会缓冲来自盘片并进入盘片的数据。大多数磁盘驱动器将尝试优化读取请求以保持磁盘旋转并最小化磁头移动。在写入盘片之前,驱动器会尝试从主机吸收尽可能多的数据,以便尽快断开主机的连接。

您的性能还取决于PC上的I / O总线流量以及磁盘和主机之间的流量。还有其他需要考虑的替代因素,例如系统任务和“同时”运行的程序。您可能无法获得与测量工具相同的精确性能。请记住,由于上面提到的开销,这些时间有一个误差因素。

如果您的平台有DMA控制器,请尝试使用它们。

答案 4 :(得分:0)

如果写入速度很重要,为什么不考虑RAID 0用于硬件配置?

  • 客户想要RAID 5。
  • 由于更好​​的容错能力而优先于RAID 0。
  • 客户对RAID 5可以提供的内容感到满意。这个问题 这里使用ATTO对硬件进行基准测试显示写入速度为每分钟2.57 GB(8MB 大块写),为什么复制工具无法实现接近呢?像每个2 GB的东西 min是我们正在关注的。到目前为止,我们每分钟只能达到~1.5 GB。

答案 5 :(得分:0)

执行此操作的正确方法是使用未缓冲的完全异步I / O.您将需要发出多个I / O以保持队列运行。这使文件系统,驱动程序和Raid-5子系统能够更好地管理I / O.

您还可以打开多个文件,并对多个文件发出读取和输入。

请注意!优秀的I / O数量以及交错读写方式将在很大程度上取决于存储子系统本身。您的程序需要高度重要,以便您可以对其进行调整。

注意 - 我相信Robocopy已得到改进 - 你试过吗?我

答案 6 :(得分:0)

我做了一些测试并得到了一些结果。 测试在100Mbps和100Mbps上进行。 1Gbps网卡。源计算机是Win2K3服务器(SATA),目标计算机是Win2k3服务器(RAID 5)。

我跑了3次测试:

1)网络阅读器 - >该程序只是通过网络读取文件。该程序的目的是找到最大的n / w读取速度。我正在使用CreateFile&amp ;;执行非BUFFERED读取ReadFile的。

2)磁盘编写器 - >该程序通过写入数据来对RAID 5速度进行基准测试。非BUFFERED写入使用CreateFile& amp; WriteFile的。

3)闪电战复制 - >该程序是文件复制引擎。它通过网络复制文件。最初的问题讨论了该计划的逻辑。我正在使用带有NO_BUFFERING的同步I / O读取&写。使用的API是CreateFile,ReadFile& WriteFile的。


以下是结果:

网络阅读器: -

100 Mbps NIC

花了148344毫秒读取768 MB,块大小为8 KB。

花了89359毫秒读取768 MB,块大小为64 KB

花了82625毫秒读取768 MB,块大小为128 KB

花了79594毫秒读取768 MB,块大小为256 KB

读取78687毫秒读取768 MB,块大小为512 KB

花了79078毫秒读取768 MB,块大小为1024 KB

读取78594毫秒读取768 MB,块大小为2048 KB

花了78406毫秒读取768 MB,块大小为4096 KB

读取78281毫秒读取768 MB,块大小为8192 KB

1 Gbps网卡

读取206203毫秒读取5120 MB(5GB),块大小为8 KB

读取77860毫秒读取5120 MB,块大小为64 KB

读取74531毫秒读取5120 MB,块大小为128 KB

花了68656毫秒读取5120 MB,块大小为256 KB

读取64922毫秒读取5120 MB,块大小为512 KB

花了66312毫秒来读取5120 MB,块大小为1024 KB

花了68688毫秒来读取5120 MB,块大小为2048 KB

读取64922毫秒读取5120 MB,块大小为4096 KB

花了66047毫秒来读取5120 MB,块大小为8192 KB

DISK WRITER: -

使用NO_BUFFERING&amp ;;在RAID 5上执行写入WRITE_THROUGH

写入大小为4MB的2048MB(2GB)数据需要68328ms。

写入大小为8MB的2048MB数据需要55985ms。

写入大小为16MB的2048MB数据需要49569ms。

写入块大小为32MB的2048MB数据需要47281ms。

仅在NO_BUFFERING

上在RAID 5上执行写入

写入大小为4MB的2048MB(2GB)数据需要57484ms。

写入大小为8MB的2048MB数据需要52594ms。

写入大小为16MB的2048MB数据需要49125ms。

写入大小为32MB的2048MB数据需要46360ms。

随着块大小的减小,写入性能会线性降低。 WRITE_THROUGH标志引入了一些性能影响

BLITZ COPY: -

1 Gbps网卡,使用NO_BUFFERING复制60 GB文件

完成复制的时间:2236735 ms。即,37.2分钟。 速度约为97 GB /每秒。

100 Mbps网卡,使用NO_BUFFERING复制60 GB文件

完成复制所需的时间:7337219 ms。即,122分钟。 速度约为30 GB /每秒。

我尝试使用Jeffrey Ritcher的10-FileCopy程序,该程序使用带有NO_BUFFERING的Async-IO。但是,结果很差。我想原因可能是块大小为256 KB ...在RAID 5上写入256 KB非常慢。

与robocopy相比:

100 Mbps NIC:Blitz Copy和robocopy每小时执行@ ~30 GB。

1 GBps网卡:闪电战复制每小时@~97 GB,而robocopy @每小时50 GB。