0

我对 win32 I/O 性能有疑问:我正在尝试使用 OpenFile/WriteFile 实现不错的写入速度。使用资源监视器(Windows 自带)我测量了以下代码的写入速度,发现它的写入速度为 2MB/秒...

HANDLE hFile = INVALID_HANDLE_VALUE;
hFile = CreateFile(
    L"test",
    (GENERIC_READ | GENERIC_WRITE),
    FILE_SHARE_READ,
    NULL,
    OPEN_ALWAYS,
    (FILE_ATTRIBUTE_NORMAL |
    FILE_FLAG_WRITE_THROUGH |
    FILE_FLAG_NO_BUFFERING),
    NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
    //OK
    unsigned long bytesWritten = 0;
    unsigned long* Buffer = (unsigned long*)malloc(4096*sizeof(unsigned long));
    ZeroMemory(Buffer, 4096); //thanks to 'bash.d'
    while (true)
    {
        /*the infinite loop is intentional
          because I wanted to see if the writing speed of 2MB/sec
          was right */
        WriteFile(hFile,
            Buffer,
            4096,
            &bytesWritten,
            NULL);
        if (bytesWritten <= 0)
        {
            break;
        }
    }
}

我尝试了以下,它是一样的......

hFile = CreateFile(
    L"test",
    (GENERIC_READ | GENERIC_WRITE),
    FILE_SHARE_READ,
    NULL,
    OPEN_ALWAYS,
    (FILE_ATTRIBUTE_NORMAL);

我在做什么错(关于写作速度)?以及如何提高写作速度?谢谢你,对不起我的英语

编辑:我在本地磁盘上写

4

2 回答 2

0

这非常有趣,与我遇到的问题类似,并且可以在 2 个不同的服务器上使用 Windows Server 2003 SP2 64 位(单个硬盘驱动器,而不是 RAID)重现。只需在循环中执行 36 字节的 WriteFile() 和 99964 字节就会产生类似的行为(我猜它与单次写入和其他一些 Windows 版本相同;这正是我碰巧使用的) . CPU 使用率一开始非常低,然后逐渐增加——在一台服务器上,测试大约 50% 的 CPU 使用率在 175GB 左右(其中大约 95% 是内核时间;60% 在我的程序中,40% 在“系统”中)。

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

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

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

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

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

尝试下面的东西是值得的......

1) 启用 FILE_FLAG_SEQUENTIAL_SCAN 标志

2) 设备管理器“磁盘策略”中的“启用高级性能”

3) 将磁盘块大小从 64 KB 更改为 4096 ...

4) 尝试 FILE_FLAG_NO_BUFFERING

于 2013-02-20T11:06:25.697 回答
0
  1. 使用绑定到完成端口的异步 IO
  2. 使用SetFileValidData预增长文件
  3. 打开手柄FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH

消费级驱动器(甚至 5400RPM)应该能够写入约 130MB/秒(单轴,无 RAID)。不应同时发生其他 IO(无头部移动)。

有关示例,请参见https://github.com/rusanu/writing-a-binary-file-in-c-very-fast 。

于 2013-02-20T11:31:27.440 回答