我正在使用CreateFile/ReadFile
和4096字节的buffersize来读取卷快照中的数据块。
我面临的问题是ReadFile
太慢,我能够在45秒内读取68439块,即267 Mb,我怎样才能提高速度?以下是我正在使用的代码的一部分,
block_handle = CreateFile(block_file,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if(block_handle != INVALID_HANDLE_VALUE)
{
DWORD pos = -1;
for(ULONG i = 0; i < 68439; i++)
{
sectorno = (i*8);
distance = sectorno * sectorsize;
phyoff.QuadPart = distance;
if(pos != phyoff.u.LowPart)
{
pos=SetFilePointer(block_handle, phyoff.u.LowPart,&phyoff.u.HighPart,FILE_BEGIN);
if (phyoff.u.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
{
printf("SetFilePointer Error: %d\n", GetLastError());
phyoff.QuadPart = -1;
return;
}
}
ret = ReadFile(block_handle, data, 4096, &dwRead, 0);
if(ret == FALSE)
{
printf("Error Read");
return;
}
pos += 4096;
}
}
我应该使用OVERLAPPED
结构吗?或者可能的解决方案是什么?
注意:代码没有线程化。
等待积极回应。
答案 0 :(得分:1)
我不太清楚你为什么要使用这些极低级别的系统功能。
我个人使用C风格的文件操作(使用fopen和fread)以及C ++风格的操作(使用fstream和read,参见this link)来读取原始二进制文件。从本地磁盘读取速度大约为100MB /秒。
在您的情况下,如果您不想使用标准的C或C ++文件操作,我的猜测是您的代码较慢的原因是由于您在每个块之后执行搜索。你真的需要为每个块调用SetFilePointer吗?如果块是顺序的,则不需要这样做。
另外,尝试不同的块大小,不要害怕超过1MB。
答案 1 :(得分:1)
您的问题是碎片数据读取。你不能通过摆弄ReadFile参数来解决这个问题。您需要对读取进行碎片整理。这里有三种方法:
对磁盘上的数据进行碎片整理
对读取进行碎片整理。也就是说,收集您需要的所有读数,但还没有读取任何内容。将读取排序为顺序。按顺序读取所有内容,尽可能跳过SetFilePointer(即顺序块)。这将大大加快总读数,但在第一次读取开始之前引入延迟。
内存映射数据。将所有数据复制到内存中并从内存中进行随机访问读取。这是否可行取决于总共有多少数据。
此外,您可能希望获得幻想,并尝试缓存。当您读取一个数据块时,可能是因为下一次读取不是连续的,但它很可能很接近。因此,当您读取一个块时,依次将大量附近数据块读入内存。在下次读取之前,检查新读取是否已经在内存中 - 从而保存了搜索和磁盘访问。测试,调试和调整这是很多工作,所以我不推荐它,除非这是一个关键任务优化。另请注意,您的操作系统和/或磁盘硬件可能已经在这些方面做了一些事情,所以要准备好看不出任何改进。
答案 2 :(得分:1)
FILE_FLAG_SEQUENTIAL_SCAN
顺序阅读。)