带有流的文件 I/O - 最佳内存缓冲区大小
Posted
技术标签:
【中文标题】带有流的文件 I/O - 最佳内存缓冲区大小【英文标题】:File I/O with streams - best memory buffer size 【发布时间】:2011-03-03 07:17:20 【问题描述】:我正在编写一个小型 I/O 库来协助一个更大的(爱好)项目。该库的一部分对文件执行各种功能,通过FileStream
对象读取/写入。在每个StreamReader.Read(...)
传递中,
我触发了一个事件,该事件将在主应用程序中用于显示进度信息。循环中进行的处理是多种多样的,但不会太耗时(例如,它可能只是一个简单的文件副本,或者可能涉及加密......)。
我的主要问题是:使用的最佳内存缓冲区大小是多少?考虑物理磁盘布局,我可以选择 2k,这将覆盖一个 CD 扇区大小,并且是 512 字节硬盘扇区的一个很好的倍数。在抽象树的更高层,您可以选择更大的缓冲区,一次可以读取整个 FAT 簇。我意识到,对于今天的 PC,我可以选择更消耗内存的选项(例如,几个 MiB),但随后我会增加 UI 更新之间的时间,并且用户会感觉到应用程序的响应速度较慢。
顺便说一句,我最终希望为托管在 FTP/HTTP 服务器上的文件(通过本地网络/fastish DSL)提供类似的接口。对于那些来说,最好的内存缓冲区大小是多少(同样,感知响应能力与性能之间的“最佳情况”权衡)?
【问题讨论】:
可能会有帮助:***.com/questions/19558435/… 我原以为操作系统或 Windows 会维护自己的硬件功能和速度配置文件,并提供一项服务,为给定的存储量和活动推荐最佳缓冲区大小(例如随机读取/writes vs 顺序读/写) - 这将消除猜测。 C# FileStream : Optimal buffer size for writing large files?的可能重复 【参考方案1】:当我直接通过流对象处理文件时,我通常使用 4096 字节。它似乎在多个 I/O 区域(本地文件系统、LAN/SMB、网络流等)上相当有效,但我还没有分析它或任何东西。很久以前,我看到几个例子使用了这个尺寸,它留在了我的记忆中。但这并不意味着它是最好的。
【讨论】:
对。我永远不会使用小于 4k 的任何东西,因为它是由虚拟内存系统(磁盘缓存所基于)管理的最小块。【参考方案2】:“视情况而定”。
您必须使用不同的缓冲区大小测试您的应用程序以确定最佳选择。你无法提前猜测。
【讨论】:
【参考方案3】:文件已被文件系统缓存缓冲。您只需要选择一个缓冲区大小,该大小不会强制 FileStream 使本机 Windows ReadFile() API 调用过于频繁地填充缓冲区。不要低于 1 KB,超过 16 KB 会浪费内存,并且对 CPU 的 L1 cache(通常为 16 或 32 KB 的数据)不友好。
4 KB 是一个传统的选择,即使它恰好跨越一个虚拟内存页面只是偶然。很难描述;您最终将测量读取缓存文件需要多长时间。如果数据在缓存中可用,它以 RAM 速度运行,5 GB/秒或更高。它将在您第二次运行测试时在缓存中,而这在生产环境中不会经常发生。文件 I/O 完全由磁盘驱动器或NIC 主导,而且速度非常慢,复制数据是小菜一碟。 4 KB 就可以了。
【讨论】:
较小的缓冲区大小(如 4-8kb)也是可取的,因为 CPU 缓存可以容纳这样的数量。但是,如果您选择较小,则可能会从内核转换中积累大量开销。 @HansPassant:我的应用程序同时处理大量小文件以及单独处理大文件。 4KB 大小是否会对小于 4KB 的文件的性能产生不利影响? 4KB 是 .net 框架使用的默认值:msdn.microsoft.com/en-us/library/dd783870.aspx 如果文档正确,在 4.5 中他们将默认值增加到 81920。 文档是正确的,.NET Reflector 显示_DefaultCopyBufferSize
的值为 0x14000
(81920 或 80K)。但是,这是用于从流复制到流,而不是缓冲数据。 BufferedStream Class 有一个 _DefaultBufferSize
和 0x1000
(4096 或 4k),这将是一个更好的类来了解 .NET 框架用于流的缓冲区大小。【参考方案4】:
我认为默认值通常是最好的 - 因此我在internal const int
变量DefaultBufferSize
中使用4096B
FileStream 类。
【讨论】:
默认并不总是最好的。对于更常见的情况,这只是一个很好的折衷方案,而不是所有负载的最佳选择。以上是关于带有流的文件 I/O - 最佳内存缓冲区大小的主要内容,如果未能解决你的问题,请参考以下文章