【问题标题】:How ReadLine works in .NETReadLine 在 .NET 中的工作原理
【发布时间】:2013-01-18 22:44:20
【问题描述】:

假设我有一个 1 GB 的文本文件,我想阅读它。如果我尝试打开此文件,我会收到“内存溢出”错误。我知道,通常的答案是“使用 StreamReader.ReadLine() 方法”。但我想知道这是如何工作的。如果使用 ReadLine 方法的程序想要获取一行,它迟早必须打开整个文本文件。据我所知,文件存储在磁盘上,可以按照“全有或全无”的原则在内存中打开。如果使用 ReadLine() 方法一次只将我的 1 GB 文本文件的一行存储在内存中,这意味着我们必须在读取 1 GB 文本文件的每一行时进行磁盘 I-O。这对性能来说不是一件很糟糕的事情吗?

我很困惑,我想了解一些细节。

【问题讨论】:

  • 仅供参考,ReadLine 不是 C# 的一部分 - 它是 .NET 的一部分。

标签: c# memory memory-management


【解决方案1】:

这意味着我们必须为我的 1 GB 文本文件的每一行磁盘 I-O

不,您的 ReadLine() 调用和物理磁盘之间有很多层,旨在不造成问题。最重要的:

  • FileStream 是为 StreamReader 执行工作的底层类,它使用缓冲区来减少 ReadFile() 调用的次数。默认大小为 4096 字节
  • ReadFile() 从文件系统缓存而不是磁盘读取文件数据。 可能会导致调用磁盘驱动程序,但这并不常见。操作系统足够聪明,可以猜测您可能会从文件中读取 更多 数据并从磁盘中预读取数据,只要这样做成本低且不使用 RAM还要别的吗。它通常会占用整个磁盘柱面的数据。
  • 磁盘驱动器本身也有缓存,通常为几兆字节。

文件系统缓存是迄今为止最重要的一个。这也是一个棘手的问题,因为它会阻止您准确地分析您的程序。当您一遍又一遍地运行测试时,您的程序实际上从不读取磁盘,只读取缓存。这使它变得不切实际地快。尽管 1 GB 的文件可能不太适合,但取决于您的机器中有多少 RAM。

【讨论】:

    【解决方案2】:

    通常会在后台打开一个FileStream 对象,该对象会从磁盘读取一大块文件并将其拉入内存。这个块作为一个 cache 供 ReadLine() 读取,因此您不必担心每个 ReadLine() 都会导致磁盘访问。

    【讨论】:

      【解决方案3】:

      糟糕的表现是什么?

      显然它应该更快,因为您有足够的内存来处理内存中的整个文件。

      虽然查找和分配一个连续的块是有代价的。

      演出是一个重要的内存块,如果你的进程有它,有什么伤害?

      交换比流式传输更容易受到伤害。

      您是否一次需要所有文件,您是否一直需要它?

      如果你去读/写。那会对你有什么影响?

      如果文件到 2 gig 怎么办?

      您可以针对一个因素进行优化。在你这样做之前,你必须确保它是正确的,最重要的是你必须记住这是一台真正的机器。你的资源是有限的,所以优化总是让彼得付钱给保罗。彼得可能会生气……

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-21
        • 1970-01-01
        • 2018-03-30
        • 2011-03-16
        • 2013-11-04
        • 2012-09-02
        • 2019-12-04
        • 1970-01-01
        相关资源
        最近更新 更多