windows 如何使文件系统缓存无效?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7405868/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:03:43  来源:igfitidea点击:

How can I invalidate the file system cache?

windowswinapicachingfilesystemsinvalidation

提问by user541686

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.

我非常需要FSCTL_DISMOUNT_VOLUME的功能,但对于系统容量。

回答by user541686

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

至少在 Windows 7 上,似乎在没有FILE_SHARE_WRITE共享权限的情况下尝试打开卷句柄会导致文件系统缓存失效即使创建失败也是如此

Thus I made a program that simply calls CreateFileto this end.

因此,我制作了一个简单地调用CreateFile此目的的程序。

Base64 encoding of the program*:

程序的 Base64 编码*:

TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAAABdRXZRRR7ikUUe4pFFHuKTGz/ikQUe4pMbOqKRBR7ilJpY2hFFHuKAAAAAAAAAABQRQAATAECAMEgRlkAAAAAAAAAAOAAIwELAQkAAAgAAAACAAAAAAAAoBIAAAAQAAAAIAAAAABAAAAQAAAAAgAABQAAAAAAAAAFAAAAAAAAAAAwAAAAAgAAlr4AAAMAAIQAABAAAAAQAAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAMABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC50ZXh0AAAAeQYAAAAQAAAACAAAAAIAAAAAAAAAAAAAAAAAACAAAGAucnNyYwAAAMABAAAAIAAAAAIAAAAKAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAABVi+yLTQiLQTyLVQyD7BBTVot0CHgz2wPxVzvTdBc5XRB1EoldEDgadAv/RRCLRRA4HAJ19YtGGEiJXfiJRfQ703QNi0X0K0X40egDRfjrA4tFEIt+GDvHcgyL2PfTO99yBDP/6xWL+PfXO8dzAov4i14gjTy7izwPA/mF0nRvg2X8AIl98ClV8ItN/ItdEAPKi1XwihQKOV38dASKCesCMskPvtkPvsory3UUhNJ0O4tN/DtNEHQz/0X8i1UM68mLVfg7VfR0TjPbO8t+BkiJRfTrBECJRfiLRfQ5Rfh3NotVDItNCOlU////i00Ii1YYO8JzF4tWJI0EQg+3BAiLVhyNBIKLBAgDwesM99A7whvAI8frAjPAX15bycNVi+yD7ByLVQhkoTAAAABTM8lWV2aJTeSF0nQVZjkKdBBmg0XkAkEPt/FmgzxyAHXwi3gMg8cMiw+JTfA7z3UKM8BfXlvJw4tVCIXSD4SRAAAAD7dBLGY5ReRzBg+3ReTrAw+3wINl+ABm0egz0maJRf5mO9BzXItxMA+3RfgDwA+3DAaJTeyLTQgPtwQIiUX0M9KNTfSF0nUDjU3sD7cBjVi/ZoP7GXcDg8AgD7fAQmaJAYP6AnXbi0XsZjtF9HI1dzP/Rfhmi0X4ZjtF/nKqi03wD7dBLGY5ReR3HBvA99jrBzsPdQeDyP+FwHULi0EY6Uz///+LTfCLCYlN8DvPD4VB////6TX///9Vi+yD7BhTag6NRehQ/3UIM9vGRehfxkXpX8ZF6nfGRetnxkXsZcZF7XTGRe5txkXvYcZF8GnGRfFuxkXyYcZF83LGRfRnxkX1c4hd9uiG/f//g8QMO8N0Eo1N+FFTVo1N/FdR/9CDxBTrB4kfiV38iR6LRfxbycNVjWwkiIHsoAACAFNWV2ptWGpzZolF5FhqdmaJReZYamNmiUXoWGpyZolF6lhqdGaJRexYai5miUXuWGpkZolF8FhqbFtmiUXyi8Nqa2aJRfRmiUX2WMZFdF/GRXVpxkV2b8ZFd2LGRWhmxkVpd8ZFanDGRWtyxkVsacZFbW7GRW50xkVvZsZFNEfGRTVlxkU2dMZFN0zGRThhxkU5c8ZFOnTGRTtFxkU8csZFPXLGRT5vxkU/csZFQEOIXUHGRUJvxkVDc8ZFRGXGRUVIxkVGYcZFR27GRUhkiF1JxkVKZcZFTEPGRU1yxkVOZcZFT2HGRVB0xkVRZcZFUkbGRVNpiF1UxkVVZcZFVldmiUUQamVYanJmiUUSWGpuZolFFFhqZWaJRRZYZolFGGozi8NmiUUaWGaJRRxqMlhmiUUeai5YZolFIGpkWGaJRSKLw2aJRSRmiUUmM8BmiUUojUUQUOgX/f//iUVwM8CNfTCrjUXkahSJRTBYM/ZWiXVkZolFLGaJRS7o8vz//2oKjU1YUVDGRVhMxkVZZMZFWnLGRVtMxkVcb8ZFXWHGRV5kxkVfRIhdYIhdYeij+///g8QUjU1kUY1NLFFWVv/Q/3VkjXXYjX386K79//+JRfhqCI1FaFD/dWTodfv//4lFbGoMjUU0UP91cOhk+///iUUwaguNRUBQ/3Vw6FP7//+JRdxqC41FTFD/dXDoQvv//4lF4GoEjUV0UP91ZOgx+///g2VwAIvwM8BAg8RAg8ZAOUX4iUV0D46EAQAAM8k5TXAPhXkBAACLVXSLRfyLBJAPtxBqQV9mO/p3SmaD+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

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('
// Open with FILE_FLAG_NO_BUFFERING
auto hFile = CreateFile(path.c_str(),
                        GENERIC_READ,
                        FILE_SHARE_READ,
                        nullptr,
                        OPEN_EXISTING,
                        FILE_FLAG_NO_BUFFERING,
                        nullptr);

/// Check
if (hFile == INVALID_HANDLE_VALUE){
    //_tprintf(TEXT("Terminal failure: unable to open file \"%s\" for read.\n"), argv[1]);
    cout << "error" << endl;
    return;
}

// Close
CloseHandle(hFile);

// Now open file with regular C++ API, and caching disabled
ifstream file(path, ios::binary | ios::ate);
') || arg[2] == _T('\') && arg[3] == _T('##代码##'))) { _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. :)

*只是为了好玩,看看你是否可以通过反汇编来弄清楚可执行文件的作用。这不是典型的可执行文件。:)

回答by Eric Grange

I've written a simple command-line utility to do that: FlushFileCache

我编写了一个简单的命令行实用程序来做到这一点:FlushFileCache

It relies on the undocumented NtSetSystemInformation functions, and can flush the various other memory pools as well.

它依赖于未记录的 NtSetSystemInformation 函数,并且还可以刷新各种其他内存池。

回答by Markus

This solution worked great: Clear file cache to repeat performance testing

此解决方案效果很好:清除文件缓存以重复性能测试

More specifically, I'm doing this:

更具体地说,我正在这样做:

##代码##

回答by Will Hartung

What David said. Create a large file, however many GB you need, and each time you want to reset your file cache, make a copy of the file. Then make sure you delete the old file.

大卫说的。创建一个大文件,无论您需要多少 GB,并且每次要重置文件缓存时,请复制该文件。然后确保删除旧文件。

So, create BIGFILE1.DAT, copy it to BIGFILE2.DAT, and then delete BIGFILE1.DAT (which removes it from the disk and the cache). Next time, just reverse the process.

因此,创建 BIGFILE1.DAT,将其复制到 BIGFILE2.DAT,然后删除 BIGFILE1.DAT(这会将其从磁盘和缓存中删除)。下一次,只需颠倒这个过程。

Addenda:

附加物:

Well, the other option is to take the files that are mapped, and copy them to new files, delete the old ones, and rename the new files back to the old ones. The cache is backed by a file. If the file "goes away" so does the cache.

好吧,另一种选择是获取映射的文件,并将它们复制到新文件中,删除旧文件,然后将新文件重命名回旧文件。缓存由文件支持。如果文件“消失”,缓存也会“消失”。

If you can identify these files, and they're not shared by the system/other running programs, this should be simple to script and, ideally, run faster than copy 6G of files around.

如果您可以识别这些文件,并且它们不会被系统/其他正在运行的程序共享,那么这应该很容易编写脚本,并且在理想情况下,运行速度比复制 6G 文件要快。

回答by John

You can use a VM and take a shapshot right after the VM boots. Resuming from a snapshot will be faster than a reboot.

您可以使用虚拟机并在虚拟机启动后立即进行快照。从快照恢复将比重新启动更快。