6

我一直在尝试找出最快的方法来编写文件复制例程以将大文件复制到 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 和其他常见的复制实用程序会在写入性能方面受到影响。因此,我编写了一个 C/C++ 程序,它使用带有NO_BUFFERING&WRITE_THROUGH标志的 CreateFile、ReadFile 和 WriteFile API。该程序模拟ESEUTIL.exe,从某种意义上说,它使用2个线程,一个用于读取,一个用于写入。读取器线程从源读取 256 KB 并填充缓冲区。一旦填充了 16 个这样的 256 KB 块,写入器线程就会将缓冲区中的内容写入目标文件。如您所见,写入器线程在 1 个镜头中写入 8MB 数据。该程序分配了 32 个这样的 8MB 块……因此,写入和读取可以并行发生。ESEUtil.exe 的详细信息可以在上面的链接中找到。注意:我在使用NO_BUFFERING.

我使用了 ATTO 等基准标记实用程序,发现我们的 RAID 5 硬件在写入 8MB 数据块时的写入速度为每秒 44MB。大约是每分钟 2.57 GB

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

谁能帮我确定问题是什么?是否有其他更快的 APICreateFile可用?ReadFileWriteFile

4

7 回答 7

7

您应该使用异步 IO 以获得最佳性能。即FILE_FLAG_OVERLAPPED使用LPOVERLAPPEDWriteFile 的参数打开文件。您可能会或可能不会获得更好的性能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 控制器中的错误的解决方法,并且不太可能仍然是问题。

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

于 2010-01-12T21:33:36.067 回答
2

不久前,我写了一篇关于异步文件 I/O 的博客文章,以及它通常如何最终实际上是同步的,除非你做的一切都恰到好处(http://www.lenholgate.com/blog/2008/02/when- are-asynchronous-file-writes-not-asynchronous.html)。

关键点是,即使您正在使用FILE_FLAG_OVERLAPPED并且FILE_FLAG_NO_BUFFERING您仍然需要预先扩展文件,以便您的异步写入不需要随时扩展文件;出于安全原因,文件扩展名始终是同步的。要预扩展,您需要执行以下操作:

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

然后...

  • 打开要写入的文件。
  • 发出写入
于 2010-01-12T22:02:04.340 回答
0

如果你不写目标,你能多快读取源文件?

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

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

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

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

您一次是否有多个正在运行的读取或写入请求?

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

于 2010-01-08T05:28:32.050 回答
0

如果写入速度那么重要,为什么不为您的硬件配置考虑 RAID 0?

  • 客户需要 RAID 5。
  • 优于 RAID 0,因为具有更好的容错性。
  • 客户对 RAID 5 的功能感到满意。这里的问题是使用 ATTO 对硬件进行基准测试显示每分钟 2.57 GB 的写入速度(8MB 块写入),为什么复制工具不能达到接近它的水平?我们正在研究的是每分钟 2 GB 的数据。到目前为止,我们每分钟只能达到约 1.5 GB。
于 2010-01-09T03:23:48.350 回答
0

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

我进行了 3 个测试:

1) Network Reader -> 这个程序只是通过网络读取文件。该程序的目的是找到最大的 n/w 读取速度。我正在使用 CreateFile 和 ReadFile 执行非缓冲读取。

2) Disk Writer -> 这个程序通过写入数据来测试 RAID 5 的速度。使用 CreateFile 和 WriteFile 执行非缓冲写入。

3) Blitz Copy -> 这个程序是文件复制引擎。它通过网络复制文件。这个程序的逻辑在最初的问题中讨论过。我正在使用带有 NO_BUFFERING 读取和写入的同步 I/O。使用的 API 是 CreateFile、ReadFile 和 WriteFile。


以下是结果:

网络阅读器:-

100 Mbps 网卡

用 148344 毫秒读取 768 MB 块大小为 8 KB。

用 89359 毫秒读取 768 MB 块大小为 64 KB

用 82625 毫秒读取 768 MB 块大小为 128 KB

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

读取 768 MB 块大小为 512 KB 花费了 78687 毫秒

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

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

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

读取 768 MB 块大小为 8192 KB 花费了 78281 毫秒

1 Gbps 网卡

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

读取 5120 MB 块大小为 64 KB 花费了 77860 毫秒

读取 5120 MB 块大小为 128 KB 花费了 74531 毫秒

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

读取 5120 MB 块大小为 512 KB 花费了 64922 毫秒

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

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

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

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

磁盘写入器:-

使用 NO_BUFFERING 和 WRITE_THROUGH 在 RAID 5 上执行写入

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

写入块大小为 8MB 的 2048MB 数据耗时 55985 毫秒。

写入块大小为 16MB 的 2048MB 数据需要 49569 毫秒。

写入块大小为 32MB 的 2048MB 数据耗时 47281 毫秒。

仅使用 NO_BUFFERING 在 RAID 5 上执行写入

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

写入块大小为 8MB 的 2048MB 数据耗时 52594 毫秒。

写入块大小为 16MB 的 2048MB 数据耗时 49125ms。

写入块大小为 32MB 的 2048MB 数据耗时 46360 毫秒。

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

闪电战副本:-

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

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

100 Mbps NIC,使用 NO_BUFFERING 复制 60 GB 的文件

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

我确实尝试使用 Jeffrey Ritcher 的 10-FileCopy 程序,它使用 Async-IO 和 NO_BUFFERING。但是,结果很糟糕。我猜原因可能是块大小为 256 KB... RAID 5 上的 256 KB 写入非常慢。

与 robocopy 相比:

100 Mbps NIC:Blitz Copy 和 robocopy 以每小时约 30 GB 的速度执行。

1 GBps NIC:Blitz Copy @ ~97 GB/小时,而 robocopy @ ~50 GB/小时。

于 2010-02-02T08:07:24.160 回答
0

正确的方法是使用无缓冲的完全异步 I/O。您将需要发出多个 I/O 以保持队列运行。这让文件系统、驱动程序和 Raid-5 子系统可以更优化地管理 I/O。

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

笔记!未完成 I/O 的最佳数量以及如何交叉读取和写入将在很大程度上取决于存储子系统本身。您的程序需要高度参数化,以便您可以对其进行调整。

注意 - 我相信 Robocopy 已经改进了 - 你试过了吗?我

于 2010-01-12T03:41:12.770 回答
0

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

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

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

于 2010-01-08T22:38:41.853 回答