在 Windows 7 中,使用设备管理器,调出磁盘的属性,然后转到“策略”选项卡,有 2 个开关项。写入缓存,这个问题与此无关。
和
[X] 关闭设备上的 Windows 写入缓存缓冲区刷新 <--- 仅此一个!
微软在该项目的选项卡上添加了免责声明。“为防止数据丢失,请不要选择此复选框,除非设备有单独的电源,允许设备在断电时刷新其缓冲区。”
简单来说,这对文件写入,文件保存,文件复制有什么改变?
1. 更改偏执程序的写入操作: (事实还是虚构)
强制执行缓存刷新是否会改变程序的写入刷新工作方式?有些程序非常专注于完成写入,无需推测,这些程序是否能够继续进行保护性写入,或者这些程序是否也会发生改变?
2. 受影响的计划类型:
哪些类型的操作/程序会或不会受此更改影响?类型,一些程序是流式的,一些程序快速写出,一些是连续的,一些是保护性的(或您可以用简单术语定义的任何其他类型)。
3. 您是否看到了什么,甚至是基准:
如果设置已开启,写作中可观察到的变化是什么?有任何观察到的行为变化的松散例子吗?或者没有观察到行为变化?
4. 延误或延迟的原因是什么:
我们知道,在大多数计算机上,这些操作大部分都非常快,数据最终将被写入。相对于驱动器的速度,时间量是否重要?
就我的问题而言,存在的风险不是问题之一,如果你想掩盖它,它就不会妨碍你。
“写入缓存缓冲区刷新”是什么意思几乎是这个的复制品,但链接适用于不同的操作系统。虽然 A 有一些信息,但链接中使用的术语也不相同。它也没有回答用户想要知道的最重要的事情,我试图在这里概述这些事情。
答案1
第一个问题中的断言是虚构的。Windows API 调用如下
FlushFileBuffers()
将要即使禁用写入缓冲区刷新,仍可确保数据完全到达物理介质。因此,那些“安全”且知道自己在做什么的程序会没事的。.NETFileStream.Flush()
等中的调用最终会调用此 API。执行大量磁盘 I/O 而不直接调用
FlushFileBuffers()
或最终调用任何辅助 API 的程序将看到最明显的性能提升。例如,如果您正在运行非必要的 I/O,即使数据丢失也没关系,例如 BOINC(如果数据丢失,您只需重新下载文件或尝试重新计算),您可以避免调用FlushFileBuffers()
,而只需调用类似 API——WriteFile()
数据将获得缓冲的需要写入,但实际上可能很长时间都不会写入,例如当文件描述符关闭时,或者当程序退出时。不幸的是,如果系统崩溃(例如 BSOD),所有数据也可能会丢失,因此真的很重要如果你正在处理任何有价值的/不可替代的数据,你做调用FlushFileBuffers()
,无论是否启用了缓冲区刷新!否则,一个简单的驱动程序错误(例如在您的图形驱动程序中)可能会导致您丢失大量数据。找不到任何基准,但您会在符合上述第二项描述的程序中注意到更多。
将数据同步到磁盘实际上并没有那么快,尤其如果频繁地在紧密循环中执行此操作。默认情况下,如果我没有记错的话,我读过《Windows Internals》一书,NTFS 默认每隔一段时间将所有脏文件系统缓冲区同步到磁盘。5秒。这显然是在稳定性和性能之间做出的合理权衡。频繁同步数据的问题在于它会让硬盘进行大量的寻道和写入。
考虑以下伪代码:
1: seek to a certain block (1)
2: write a couple megabytes of data into blocks starting at (1)
3: wait 2 seconds
4: seek to another block (2)
5: write some more megabytes of data into blocks starting at (2)
6: seek back to block (1)
7: write some more megabytes of data into blocks starting at (1)
8: wait 10 minutes
9: seek to block (1)
10: write some megabytes of data into blocks starting at (1)
11: wait 5 seconds
12: seek to block (2)
13: write some megabytes of data into blocks starting at (2)
14: explicit call to FlushFileBuffers()
具有 5 秒自动缓冲液冲洗功能在:
- 第 2、5 和 7 行的写入发生在 RAM 中并且磁盘不动,直到自第一次写入以来已经过去 5 秒,然后最新数据(从第 7 行开始)被写入块 (1),并且唯一写入块 (2) 的数据被写入。
- 第 10 行和第 13 行的写入操作会覆盖块 (1) 和 (2) 中的数据,因此必须再次将其写入磁盘
- 因此,块(1)被写入的总次数到内存为 3,并且到磁盘,2. 块(2)被写入的总次数到内存为 2,并且到磁盘,2.
具有 5 秒自动缓冲液冲洗功能离开(你问题中的复选框的效果):
- 第 2、5、7、10 和 13 行的写入发生在 RAM 中磁盘不动,直到执行第 14 行,最新数据(来自第 10 行和第 13 行)才写入块(1)和(2)。第 2、5 和 7 行的旧数据永远不会到达硬盘!
考虑到一个繁忙的系统每秒可能会有数百到数万次文件写入,这对于性能来说非常好,尤其在传统旋转硬盘上(在 SSD 上就没那么令人印象深刻了)。一般来说,RAM 比硬盘快 20 倍,尽管 SSD 的差距较小。
他们说你应该使用电池备份的原因是,你不希望因为程序员懒惰没有打电话而导致 35 分钟的写入数据缓冲在 RAM 中,而没有写入磁盘FlushFileBuffers()
,然后发生电源故障。当然,电池备份不能保护你免受导致 BSOD 的驱动程序错误的影响……
答案2
支持聊天机器人 John Cavil 的回答,我写了一个小测试程序:
// ...
byteEx btTest;
btTest.resize(1024*1024, 0xff); // 1MB data
CSysFile sfTest(byT("test.bin"));
swTest.Start(); // Begin timing by call `QueryPerformanceCounter` API
for (UINT i=0; i<10000; ++i) // Write 1MB data for 10000 times
{
sfTest.SeekBegin();
sfTest.Write(btTest); // Call `WriteFile` API
// sfTest.Flush(); // Call `FlushFileBuffers` API
}
swTest.Stop(); // Calculate the time-consuming start from `swTest.Start() `
// ...
并在启用“关闭设备上的 Windows 写入缓存缓冲区刷新”选项的三星 950pro NVMe 磁盘上运行它。
结果是:
D:\tmp> test // without sfTest.Flush();
00:00:00.729766 // use 0.73 seconds without FlushFileBuffers()
D:\tmp> test // with sfTest.Flush();
00:00:06.736167 // use 6.74 seconds with FlushFileBuffers()
所以你可以看到FlushFileBuffers
系统没有忽略该请求(FlushFileBuffers
即使启用了该选项,Windows 也不会忽略调用)。