为什么大块的文件I/O比小块大?

Meh*_*dad 8 windows file-io winapi readfile

如果ReadFile使用大小为32 MB的内容调用一次,则显然比读取具有较小块大小的等效字节数(如32 KB)要长.

为什么?

(不,我的磁盘不忙.)


编辑1:

忘了提 - 我正在这样做FILE_FLAG_NO_BUFFERING!


编辑2:

奇怪的...

我再也无法访问我的旧机器了(PATA),但是当我在那里测试时,它花了大约2倍的时间,有时更多.在我的新机器(SATA)上,我只有25%的差异.

这是一段要测试的代码:

#include <memory.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

int main()
{
    HANDLE hFile = CreateFile(_T("\\\\.\\C:"), GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING, FILE_FLAG_NO_BUFFERING /*(redundant)*/, NULL);
    __try
    {
        const size_t chunkSize = 64 * 1024;
        const size_t bufferSize = 32 * 1024 * 1024;
        void *pBuffer = malloc(bufferSize);

        DWORD start = GetTickCount();
        ULONGLONG totalRead = 0;
        OVERLAPPED overlapped = { 0 };
        DWORD nr = 0;
        ReadFile(hFile, pBuffer, bufferSize, &nr, &overlapped);
        totalRead += nr;
        _tprintf(_T("Large read: %d for %d bytes\n"),
            GetTickCount() - start, totalRead);

        totalRead = 0;
        start = GetTickCount();
        overlapped.Offset = 0;
        for (size_t j = 0; j < bufferSize / chunkSize; j++)
        {
            DWORD nr = 0;
            ReadFile(hFile, pBuffer, chunkSize, &nr, &overlapped);
            totalRead += nr;
            overlapped.Offset += chunkSize;
        }
        _tprintf(_T("Small reads: %d for %d bytes\n"),
            GetTickCount() - start, totalRead);
        fflush(stdout);
    }
    __finally { CloseHandle(hFile); }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果:

大读:1076表示67108864字节
小读:842表示67108864字节

有任何想法吗?

MSN*_*MSN 1

您的测试包括读取文件元数据所需的时间,特别是文件数据到磁盘的映射。如果关闭文件句柄并重新打开它,则每个文件句柄应该得到相似的计时。我在本地进行了测试以确保这一点。

对于大量碎片,影响可能更严重,因为您必须读入更多文件到磁盘的映射。

编辑:需要明确的是,我在本地运行了此更改,并且看到大读取和小读取的时间几乎相同。重复使用相同的文件句柄,我从原始问题中看到了类似的时间。