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

前端之家收集整理的这篇文章主要介绍了c# – 寻求的解释/信息:Windows使用“fsync”写入I / O性能(FlushFileBuffers)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这个问题是我发布的早期问题的后续跟进: Windows fsync (FlushFileBuffers) performance with large files.我找到了一个可能的解决方案,但也提出了新的问题.

在针对fsynced写入的不同场景进行基准测试时,我发现了许多令人惊讶的结果.我希望有人可以帮助解释或指出我解释这些结果的信息方向.

这个基准测试的作用是将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笔记本电脑)的所有这些选项组合的发现.

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

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

通过内存映射文件写入文件时,在使用无缓冲/写入标志打开文件的情况下,可以看到性能相同的指数下降.在这里,如果文件有一个字节写入其最后位置,性能会更差.

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

对于具有“fsync”刷新的缓冲写入文件(即不通过memmap),性能现在已经从指数衰减变为恒定趋势.但是,它现在需要比以前的测试方案更长的时间.吞吐量是一个恒定的1.5 MB / s,之前它以大约20 MB / s开始,以指数方式衰减到大约1.5 MB / s.看起来可能的解释是文件元数据也会在每次刷新时被刷新,从而导致完整的磁盘革命以寻找元数据的位置.

对于“直写”到文件场景,写入最后一个字节的结果现在是相同的,与霍华德的解释所期望的一致.

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

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

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

总结为基于对我的系统的观察到目前为止的高度推测性结论:

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

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

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

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

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

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

猜你在找的C#相关文章