【问题标题】:Reading a large number of files quickly快速读取大量文件
【发布时间】:2017-10-05 10:00:03
【问题描述】:

我有大量 (>100k) 相对较小的文件 (1kb - 300kb) 需要读取和处理。我目前正在遍历所有文件并使用File.ReadAllText 读取内容、处理它,然后读取下一个文件。这很慢,我想知道是否有优化它的好方法。

我已经尝试过使用多个线程,但由于这似乎是 IO 绑定,我没有看到任何改进。

【问题讨论】:

  • 哪个部分占用的时间最长?加载文件还是处理它们?
  • @NickLarsen:正在加载文件。
  • 即使加载它们花费的时间最长,多线程仍然可以为您带来好处,因为它至少可以从总运行时间中移除(大部分)处理方面。
  • 正在更新文件并将它们写回,还是只是计算文件集的某种功能?

标签: c# .net-2.0


【解决方案1】:

您很可能是正确的 - 读取这么多文件可能会限制您的潜在加速,因为磁盘 I/O 将是限制因素。

话虽如此,您很可能可以通过将数据处理传递到单独的线程来进行小幅改进。

我建议尝试使用单个“生产者”线程来读取您的文件。该线程将受到 IO 限制。在读取文件时,它可以将“处理”推送到 ThreadPool 线程(.NET 4 任务也适用于此)以便进行处理,这将允许它立即读取下一个文件。

这至少会从总运行时间中减少“处理时间”,使您的工作总时间几乎与磁盘 IO 一样快,前提是您有一两个额外的内核可以使用......

【讨论】:

  • 多个生产者写入线程安全数据结构会增加磁盘访问吞吐量吗? (好奇你为什么只推荐一位制作人)
【解决方案2】:

我要做的是在单独的线程中进行处理。我会读入一个文件并将数据存储在队列中,然后读入下一个文件等等。

在您的第二个线程中,让线程从该队列中读取数据并进行处理。看看有没有帮助!

【讨论】:

    【解决方案3】:

    可能是磁盘寻道时间是限制因素(这是进行 Make 时最常见的瓶颈之一,通常涉及大量小文件)。愚蠢的文件系统设计有一个目录条目,并坚持一个指向文件磁盘块的指针,并且保证每个文件至少有 1 次查找。

    如果您使用的是 Windows,我会切换到使用 NTFS(将小文件存储在 目录条目中(--> 每个文件保存一次磁盘搜索)。我们也使用磁盘压缩, (更多计算,但 CPU 便宜且快速,但磁盘空间更少 --> 读取时间更少);如果您的文件都很小,这可能不相关。如果您在哪里,可能有一个 Linux 文件系统等价物。

    是的,你应该启动一堆线程来读取文件:

         forall filename in list:   fork( open filename, process file, close filename)
    

    您可能需要限制它以防止线程耗尽,但我会为数百个而不是 2 或 3 个。如果您这样做,您是在告诉操作系统它可以读取磁盘上的很多位置,它可以通过磁盘放置对多个请求进行排序 (elevator algorithm),这也有助于减少头部运动。

    【讨论】:

      【解决方案4】:

      我会推荐“多线程”来解决这个问题。当我阅读您的帖子答案时,突然发现Reed Copsey的答案会如此富有成效。您可以在此link 上找到由Elmue 准备的此解决方案的示例。我希望这很有用,感谢Reed Copsey。 问候

      【讨论】:

        【解决方案5】:

        我同意 Reed 和 Icemanind 的 cmets。另外,考虑如何增加磁盘IO。例如,将文件分布在多个磁盘上,以便可以并行读取它们并使用更快的磁盘,例如 SSD 或 RAM 磁盘。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-01
          • 2016-02-21
          • 1970-01-01
          • 2013-10-28
          • 1970-01-01
          相关资源
          最近更新 更多