0

使用标志 FILE_FLAG_IO_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 时慢的原因的想法。谢谢。

4

1 回答 1

0

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

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

于 2013-07-23T13:58:06.457 回答