使用标志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的原因分享您的想法。感谢。
答案 0 :(得分:0)
我希望您测量的是打开和关闭文件的时间。相当多的文件。您应该能够在大约一秒钟内从磁盘读取57MB。所以开销似乎是文件打开而不是读数。您应该使用更少但更大的文件再试一次。比如创建20个100MB文件并阅读它们。至少在您的系统上,看起来打开FILE_FLAG_NO_BUFFERING
的文件比没有文件的速度慢。
无论如何,不要指望FILE_FLAG_NO_BUFFERING
加快速度。与从磁盘中提取数据相比,从文件句柄缓冲区复制到缓冲区所花费的时间是微不足道的。