FILE_FLAG_IO_BUFFERING减慢了同步读取操作

时间:2013-07-22 06:32:55

标签: c++ windows winapi file-io

使用标志FILE_FLAG_IO_BUFFERING读取一组没有缓冲(跳过文件缓存)的文件应该比正常读取更快(不使用此标志)。更快的原因是'no buffering'机制将跳过系统文件缓存并直接读入应用程序的缓冲区。
应用程序在冷环境中运行(在磁盘碎片整理,机器重启后),以便在运行之前不会使用相关文件缓存系统文件缓存。
这是关于这些API和标志的msdn文档。

然而,我遇到了完全不同的表现行为。在使用FILE_FLAG_IO_BUFFERING标志创建文件句柄之后,我一个接一个地同步读取一组文件。读取文件集所需的时间是29秒。如果我在没有使用此标志的情况下正常读取(再次在应用程序的冷运行中,当文件缓存不保存相关文件时),则所需时间约为24秒。

详情
文件总数:1939
文件总大小(总和):57 MB
使用FLAG_IO_NO_BUFFERING:29秒(读取时间)
没有FLAG_IO_NO_BUFFERING:24秒(阅读时间)

以下是实现读取的代码:

DWORD ReadFiles(std::vector<std::string> &filePathNameVectorRef)
{
    long totalBytesRead = 0;    
    for(all file in filePathNameVectorRef)
        totalBytesRead += Read_Synchronous(file);           
    return totalBytesRead;
}

DWORD Read_Synchronous(const char * filePathName)
{
    DWORD accessMode = GENERIC_READ;
    DWORD shareMode = 0;
    DWORD createDisposition = OPEN_EXISTING;
    DWORD flags = FILE_FLAG_NO_BUFFERING;
    HANDLE handle = INVALID_HANDLE_VALUE;
    DWORD fileSize;
    DWORD bytesRead = 0;
    DWORD bytesToRead = 0;
    LARGE_INTEGER li;
    char * buffer;  
    BOOL success = false;


    handle = CreateFile(filePathName, accessMode, shareMode, NULL, createDisposition, flags, NULL);
    if(handle == INVALID_HANDLE_VALUE)
          return 0;

    GetFileSizeEx(handle, &li);
    fileSize = (DWORD)li.QuadPart;

    bytesToRead = (fileSize/g_bytesPerPhysicalSector)*g_bytesPerPhysicalSector;
    buffer = static_cast<char *>(VirtualAlloc(0, bytesToRead, MEM_COMMIT, PAGE_READWRITE));

    if(buffer == NULL)
         goto RETURN;

    success = ReadFile(handle, buffer, bytesToRead, &bytesRead, NULL);

    if(!success){
        fprintf(stdout, "\n Error occured: %d", GetLastError());
        return 0;
    }

    free(buffer);

RETURN:
    CloseHandle(handle);
    return bytesRead;
}

请与您认为此代码运行速度低于未使用FILE_FLAG_NO_BUFFERING的原因分享您的想法。感谢。

1 个答案:

答案 0 :(得分:0)

我希望您测量的是打开和关闭文件的时间。相当多的文件。您应该能够在大约一秒钟内从磁盘读取57MB。所以开销似乎是文件打开而不是读数。您应该使用更少但更大的文件再试一次。比如创建20个100MB文件并阅读它们。至少在您的系统上,看起来打开FILE_FLAG_NO_BUFFERING的文件比没有文件的速度慢。

无论如何,不​​要指望FILE_FLAG_NO_BUFFERING加快速度。与从磁盘中提取数据相比,从文件句柄缓冲区复制到缓冲区所花费的时间是微不足道的。