我试图扫描一个1.4 GB的1000个文件的文件夹,有时在很多计算机上需要10分钟,这是非常不可接受的。我在下面编码,我想知道我如何能加快它,如果它甚至可能。注意,文件永远不会超过250MB,因此需要缓冲区。此代码针对文件夹中的每个文件运行。
HANDLE hFile = CreateFileA(szFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD dwSize = GetFileSize(hFile, NULL);
if (dwSize != -1)
{
if (dwSize > 0)
{
DWORD dwChecksum = 0;
DWORD dwReadS = 0;
DWORD dwReadFar = 0;
bool bFailed = false;
if (ReadFile(hFile, pFileBuffer, 250000000, &dwReadS, NULL))
{
dwChecksum = CalculateChksum(pFileBuffer, dwReadS);
}
else
{
bFailed = true;
}
}
}
}
DWORD CalculateChksum(BYTE* pData, int len, DWORD CRC)
{
DWORD crc = CRC;
const DWORD* current = (const DWORD*)pData;
while (len >= 4)
{
crc = *current++ + crc;
len -= 4;
}
const BYTE* currentChar = (const BYTE*)current;
while (len-- > 0)
crc = *currentChar++ + crc;
return crc;
}
当文件被部分读取时,CPU处于空闲状态。为了加快速度,可以读取1mb的数据块并对其进行解码。将FILE_FLAG_SEQUENTIAL_SCAN
传递给CreateFile
,这样Windows将知道预取下一个块。
另外,确保使用优化的构建进行测试。您的函数足够简单,单个线程应该能够跟上磁盘I/O,但在调试构建中可能不是这样。
顺便说一句,你知道那不是CRC吗?您的算法无法捕获诸如端序交换之类的琐碎修改。
事先获取整个文件列表并创建一个列表。创建一个包含20个线程的池。让每个线程获取下一个未处理的文件,处理它并更新CRC。这将给你一个很大的加速。
对于类似的问题,我已经看到了巨大的改进。我有一次需要打开50K的文件,然后计算一些ACL相关的内容。在一个SSD上有20个线程的情况下,我能够将这个时间缩短到30秒。初始的单线程模式需要3分钟。