gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 13:23:21 28 4
gpt4 key购买 nike

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

平均文件大小约为 2 GB。

有 2 个窗口框(都运行 win2k3)。第一个框是源,大文件所在的位置。第二个盒子有一个 RAID 5 存储。

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

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

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

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

谁能帮我确定问题出在哪里?是否有比 CreateFileReadFileWriteFile 更快的 API 可用?

最佳答案

您应该使用异步 IO 以获得最佳性能。即使用 FILE_FLAG_OVERLAPPED 打开文件并使用 WriteFile 的 LPOVERLAPPED 参数。使用 FILE_FLAG_NO_BUFFERING 可能会也可能不会获得更好的性能。你必须测试才能看到。

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

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

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

您当前使用的数字似乎是合理的,但可能不是最佳的。此外,我相当确定 FILE_FLAG_WRITE_THROUGH 会阻止使用磁盘缓存,因此会降低您的性能。

您还需要注意,使用 CreateFile/WriteFile 复制文件不会复制元数据,例如时间戳或 NTFS 上的备用数据流。您将不得不自己处理这些事情。

实际上用您自己的代码替换 CopyFile 是一项相当多的工作。

附录:

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

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

关于c++ - 提高高速文件复制的写入速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2025694/

28 4 0
文章推荐: jquery - 奇怪的
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com