windowswinapicachingfilesystemsinvalidation

How can I invalidate the file system cache?


I want to measure/optimize the "cold boot" startup performance of an application, and it's difficult to do this without an actual reboot, which is obviously not an ideal solution.

Is there a way I could invalidate entire system's file cache, so that mapped page accesses actually cause a disk access, so that I can measure the time my program takes to start up?

Information:

I pretty much need FSCTL_DISMOUNT_VOLUME's functionality, but for the system volume.


Solution

  • At least on Windows 7, it seems that attempting to open a volume handle without FILE_SHARE_WRITE sharing permissions causes the file system cache to be invalidated, even if the creation fails.

    Thus I made a program that simply calls CreateFile to this end.

    Download the program* from its Base64 version here:

    <!-- Click "Run Snippet", then Right-Click -> Save As... -->
    <a href="data:application/octet-stream;base64,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SmaD+lp3RGaDeAI6dT0Pt1AEZoXSdAxmg/pcdS5mOUgGdShqXFlqLmaJjdj//f9miY3a//3/WWpcZomN3P/9/1lqBGaJjd7//f9Zi9APtwAz/2Y7x3QWD7fAZomETdj//f9BQkIPtwJmO8d17VdXagNXM8BqAWaJhE3Y//3/agGNhdj//f9Q/1Xgg/j/dAlQ/1Xc6b8AAAD/VTBqIIvQWYlVcDvRD4SsAAAAg/oFD4SjAAAAakVYanJmiUUAWGpvi/hmiX0CZol9BF9qJWaJfQaL+GaJfQiL+WaJfQpfamRmiX0MX2pjZol9Dov5Zol9EF9qZWaJfRKL+2aJfRRfamFmiUUaZol9Fl9qaVhqbmaJRRxYamdmiUUeWGolZolFIFhqc2aJRSRYZolFJmoKWGaJRSgzwGaJRSqLRfxmiU0ii010Zol9GP80iI1FAFJQVv9VbIPEEP9FdItFdDtF+A+MfP7//4tFcF9eW4PFeMnDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAQAYAAAAGAAAgAAAAAAAAAAABAAAAAAAAQABAAAAMAAAgAAAAAAAAAAABAAAAAAAAQAJBAAASAAAAFggAABlAQAA5AQAAAAAAAA8YXNzZW1ibHkgeG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYxIiBtYW5pZmVzdFZlcnNpb249IjEuMCI+DQogIDx0cnVzdEluZm8geG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYzIj4NCiAgICA8c2VjdXJpdHk+DQogICAgICA8cmVxdWVzdGVkUHJpdmlsZWdlcz4NCiAgICAgICAgPHJlcXVlc3RlZEV4ZWN1dGlvbkxldmVsIGxldmVsPSJyZXF1aXJlQWRtaW5pc3RyYXRvciIgdWlBY2Nlc3M9ImZhbHNlIj48L3JlcXVlc3RlZEV4ZWN1dGlvbkxldmVsPg0KICAgICAgPC9yZXF1ZXN0ZWRQcml2aWxlZ2VzPg0KICAgIDwvc2VjdXJpdHk+DQogIDwvdHJ1c3RJbmZvPg0KPC9hc3NlbWJseT5QQURQQURESU5HWFhQQURESU5HUEFERElOR1hYUEFERElOR1BBRERJTkdYWFBBRERJTkdQQURESU5HWFhQQURESU5H" download="FlushFileSystemCache.exe">FlushFileSystemCache.exe</a>

    Source

    // Usage: ClearCache C: D:
    #include <tchar.h>
    #include <stdio.h>
    #include <windows.h>
    
    int _tmain(int argc, LPTSTR argv[]) {
        LPCTSTR DOS_PREFIX = _T("\\\\.\\");
        for (int i = 1; i < argc; i++) {
            LPTSTR arg = argv[i];
            LPTSTR path = (LPTSTR)calloc(
                _tcslen(arg) + _tcslen(DOS_PREFIX) + 1, sizeof(*arg));
            __try {
                if (_istalpha(arg[0]) && arg[1] == _T(':') &&
                   (arg[2] == _T('\0') ||
                    arg[2] == _T('\\') && arg[3] == _T('\0')))
                { _tcscat(path, DOS_PREFIX); }
                _tcscat(path, arg);
                HANDLE hFile = CreateFile(path,
                    FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
                if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); }
                else {
                    DWORD le = GetLastError();
                    if (le != ERROR_SHARING_VIOLATION && le != ERROR_ACCESS_DENIED)
                    {
                        _ftprintf(stderr, _T("Error %d clearing %s\n"), le, argv[i]);
                        return le;
                    }
                }
            } __finally { free(path); }
        }
        return 0;
    }
    

    * Just for fun, see if you can figure out what the executable does by disassembling it. It's not your typical executable. :)