加快文件扫描的CRC算法



我试图扫描一个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分钟。

最新更新