win32 I / O性能问题

时间:2013-02-20 10:51:21

标签: c++ winapi io

我遇到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);

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

编辑: 我正在写一个本地磁盘

2 个答案:

答案 0 :(得分:0)

这非常有趣,类似于我遇到的问题,并且可以在Windows Server 2003 SP2 64位(单个硬盘驱动器,而不是RAID)的2个不同服务器上重现。简单地在循环中执行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

答案 1 :(得分:0)

  1. Use async IO bound to a completion port
  2. 使用SetFileValidData
  3. 预生成文件
  4. 使用FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH
  5. 打开句柄

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

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