寻求的解释/信息:Windows使用“fsync”(FlushFileBuffers)写入I / O性能

时间:2013-08-19 07:48:41

标签: c# windows performance mmap fsync

这个问题是我发布的早期问题的后续跟进:Windows fsync (FlushFileBuffers) performance with large files。在哪里我找到了可能的解决方案,但也有新问题。

在为不同的写作基准测试时,我发现了许多令人惊讶的结果。我希望有人可以帮助解释或指出我解释这些结果的信息方向。

此基准测试的作用是将8个页面(32 K)的批量顺序写入随机块(大4096字节)到文件,然后刷新写入。它总共写了200000页,总计800 MB和25000次刷新。在开始写入之前,文件的大小设置为其最终长度。

它支持总共4个选项,其中包含所有组合:

  • 在编写批处理或正常刷新(NS)后执行" fsync" / FlushFileBuffers操作(FS)。
  • 在开始写入(LB)或将文件保留为空(E)之前,将单个字节写入文件的最后位置。
  • 使用普通缓冲写入(B)或无缓冲/写入(WT)写入(使用FILE_FLAG_NO_BUFFERING和FILE_FLAG_WRITE_THROUGH)。
  • 直接写入文件流,即通过文件句柄(F)或使用内存映射(MM)间接写入文件。

下表总结了我对我的系统(具有慢速主轴磁盘的64位Win 7笔记本电脑)的所有这些选项组合的发现。

Benchmark results for all combinations of options

我发现的是" fsynced"缓冲写入随着文件大小呈指数级下降到令人难以置信的低吞吐量,这使得与大文件组合使用时不可行。如果文件的最后一个字节写入(选项LB),吞吐量甚至更低,所以我担心在随机而不是顺序写入情况下,性能将更加显着。

然而令人惊讶的是,对于无缓冲/写入I / O,吞吐量保持不变,与文件大小无关。最初(前100-200 MB)它的吞吐量低于缓冲写入,但之后平均吞吐量迅速增加,并且完成写入800 MB的速度更快。更令人惊讶的是,如果文件的最后一个字节写入,吞吐量会增加2倍。

当通过内存映射文件写入文件时,在使用无缓冲/写入标志打开文件的情况下,也会看到性能相同的指数下降。而且,如果文件的字节写入其最后位置,性能会更差。

更新 基于Howard的解释herehere,我在开始写入之前不重新创建新文件(即打开现有的完全写入的文件并覆盖它)。我已更新原始问题中的代码,以反映此测试所做的更改。结果部分符合他对Linux的解释和发现。但有一些值得注意的例外。下表提供了结果,红色突出显示了重大变化,蓝色突出显示未发生变化的情况,这是令人惊讶的(即如果霍华德的解释中提到的效果是唯一正在发挥的效果,则不符合预期)。 / p>

Results when overwriting existing file

使用" fsync"对文件进行缓冲写入(即不通过memmap);同花顺,现在表现已从指数衰减变为恒定趋势。但是,它现在比以前的测试场景需要更长的时间。吞吐量是一个恒定的1.5 MB / s,之前它以大约20 MB / s开始,以指数方式衰减到大约1.5 MB / s。似乎可能的解释是文件元数据也会在每次刷新时刷新,从而导致完整的磁盘革命以寻找元数据的位置。

对于#34;通过"在文件方案中,写下最后一个字节的结果现在是相同的,与霍华德的解释一致。

然而,有一个值得注意的例外,对内存映射的写入并没有真正改变,这是令人惊讶的。它们在写入性能方面仍然表现出相同的指数衰减(从大约20 MB / s衰减到1.8 MB / s开始)。这表明正在发挥不同的机制。一个值得注意的例外是如果基础文件是在没有FILE_FLAG_WRITE_THROUGH和" fsync"的情况下创建的。进行冲洗。此方案现在显示恒定(差)性能,吞吐量约为1.6 MB / s。由于我有些疑惑,我多次重复这种情况,每次给出相同的结果。

为了弄清楚一点,我还使用较小的文件(50000页,总计200 MB)重新进行此测试,以确认fsync性能(对于缓冲I / O)实际上取决于文件大小。结果显示如下,值得特别注意的结果用红色突出显示。

Results on smaller file

这些结果与较大文件的结果很好地相关。值得注意的变化是,对于那些突出显示的内容,写入更有效,它们似乎达到了大约7 MB / s的限制。

根据迄今为止在我的系统上的观察结果总结为高度推测结论:

  • " FSYNC"具有缓冲IO的文件(即没有FILE_FLAG_WRITE_THROUGH标志)的Windows上的性能随着已经写入文件的字节数呈指数级递减。原因似乎是每次都需要刷新文件元数据,这会导致磁盘搜索到文件的开头。
  • " FSYNC"写入内存映射文件时,Windows上的性能也会显示指数级下降的性能。我目前没有解释造成这种情况的确切机制。

鉴于这种观察到的性能,至少在我的用例中,这两个I / O选项并不代表可行的解决方案。

根据Greg's suggestion我将在关闭Windows磁盘缓存的情况下重新运行测试,并且我还将运行霍华德提供的benchmark code以排除由于错误而导致结果出现偏差的可能性我自己的。

更新2 我已完成测试,目前正在编译结果。为了不写"完整的历史记录"我将用结果,结果和一些结论的摘要替换这个问题的当前内容。霍华德在这个问题上的答案,以及在.NET代码旁边运行他的c基准代码的能力是最有用的。应用程序的结果相关性很好。 Rlb的回答帮助我更好地理解了什么是合理的数字"与磁盘有关。谢谢。

问题的一部分仍未得到答复。特别与在写入存储器映射时观察到的降低(和依赖于文件大小)性能有关。它可能与搜索/元数据刷新有关,但我还不清楚为什么/如何。

2 个答案:

答案 0 :(得分:4)

您看到同步运行速度呈指数级下降,因为这些并不是您认为的纯顺序工作负载。由于每次都是以新文件开头,因此您的写入会增加文件,并且需要在文件系统中更新元数据。这需要多次搜索,随着文件的增长,从文件末尾到元数据的搜索需要越来越长的时间。我也错误地在你的另一个问题上发布了这个,请在​​那里看到完整的答案:https://stackoverflow.com/a/18429712/894520

答案 1 :(得分:0)

尝试关闭磁盘缓存并重新发布?

否则这些指标是无意义的(Fsync和直写可能实际上不会命中磁盘)。 Windows默认启用磁盘缓存控制器缓存..

格雷格