【问题标题】:What is the fastest way to write hundreds of files to disk using C#?使用 C# 将数百个文件写入磁盘的最快方法是什么?
【发布时间】:2011-01-11 03:55:27
【问题描述】:

我的程序应该将数百个文件写入磁盘,由外部资源(网络)接收 每个文件都是一个简单的文档,我目前将其以 GUID 的名称存储在特定文件夹中,但是创建数百个文件、写入、关闭是一个漫长的过程。

有没有更好的方法将这些文件存储到磁盘? 我已经找到了一个解决方案,但我不知道它是否是最好的。

首先,我创建了 2 个文件,其中一个类似于分配表,第二个是一个巨大的文件,用于存储我的文档的所有内容。但是从这个文件中读取将是一场噩梦。也许内存映射文件技术可以提供帮助。使用 30GB 或更多会产生问题吗?

编辑:在磁盘上存储 1000 个文本文件的最快方法是什么? (写操作频繁执行)

【问题讨论】:

  • 请提供更多信息 - 这些文件的正常访问模式是什么?写一次读多少?写很多?预计文件大小会改变吗?
  • 这些文件通常有多大?
  • 您无法使用代码加速磁盘 I/O。获得更快的磁盘。就像您在 dbase 服务器中找到的一样。
  • 有数百个磁盘驱动器连接到您的计算机。 :-)
  • 每个文件平均为 5KB,但有很多,例如我需要像这样写 1000 个文件。并且大量的 IO 会影响我服务器的其他服务我想找到一种解决方案来减少 IO,从而减少我的其他服务的响应时间加上(这些写操作在事务范围内执行,因此开销很大)

标签: c# .net file-io memory-mapped-files


【解决方案1】:

这类似于Subversion 将其存储库存储在磁盘上的方式。存储库中的每个修订都存储为一个文件,存储库为每 1000 个修订使用一个文件夹。这似乎表现得相当好,除非文件很有可能变得碎片化或彼此相距更远。 Subversion 允许您将每个 1000 个修订文件夹打包到一个文件中(但这很好用,因为修订一旦创建就不会被修改。

如果您打算经常修改这些文档,您可以考虑使用嵌入式数据库来为您管理实体文件(Firebird 是一个不错的,没有任何大小限制)。这样您就不必自己管理文件的增长和组织(当您开始修改实体文件中的文件时,这可能会变得复杂)。如果您使用单独的服务/进程来管理数据库并与之通信,这也将有助于解决并发访问(读/写)的问题。新版本的 Firebird (2.5) 支持多进程访问数据库,即使在使用嵌入式服务器时也是如此。这样您就可以对文件存储进行多次访问,而无需运行数据库服务器。

【讨论】:

    【解决方案2】:

    您应该做的第一件事是分析您的应用。特别是您希望获得有关磁盘队列长度的计数器。您的队列长度shouldn't be any more than 1.5 to 2 乘以您拥有的磁盘轴数。

    例如,如果您有一个单磁盘系统,那么队列长度不应超过 2。如果您有 3 个磁盘的 RAID 阵列,则应该超过 6。

    验证您确实是写绑定的。如果是这样,那么提高执行大量写入性能的最佳方法是购买具有非常快写入性能的磁盘。请注意,大多数 RAID 设置都会导致性能下降。

    如果写入性能至关重要,那么将存储分散到多个驱动器上可能会奏效。当然,对于需要读取该信息的任何应用程序,您都必须考虑到这一点。而且您仍然需要购买快速驱动器。

    请注意,并非所有驱动器都是平等的,有些驱动器比其他驱动器更适合高性能。

    【讨论】:

      【解决方案3】:

      使用ThreadPool 怎么样?

      即对于每个接收到的“文件”,在线程池线程中加入一个写入函数,该线程实际上将数据保存到磁盘上的文件中。

      【讨论】:

      • @Uwe 驱动器不支持并发写操作,它们只有一组磁头。添加线程可能会使其性能更差
      • 是的,排队通常是个好主意,因此将任务委托给另一个专用线程。如果您要将它排队到线程池中,您可能会遇到一个经典问题,即磁盘超载,因此工作项运行时间越来越长。最终,线程池开始增加线程数,这会导致正反馈循环,事情就会失控。
      • 我知道这是 HDD 的问题,我怀疑更快的 SSD 问题会小得多,但对 SSD 的了解还不够,无法真正回答。我怀疑它们也不允许并发操作。
      • @Uwe Keim:关于 SSD,问题实际上与吞吐量有关,而不是与驱动器的任何物理设计有关。 CPU 只有一个连接到驱动器(通过 SATA 电缆),因此最大磁盘写入速度在顶端受到 SATA 管道大小或驱动器写入速度的限制。在多个线程上写入只是在 SATA 连接上交错数据。在 SSD 上,由于没有移动磁头,浪费会更少,但由于您仍然受到吞吐量的限制,您最好按顺序写入,因为这样可以减少 CPU 开销。
      • @Cedrik:我不同意。磁盘中是否有硬件缓冲区无关紧要,CPU 可以远远超过任何磁盘(甚至 SSD)的性能,因此只需运行单个线程,您就可以在磁盘运行时继续填充缓冲区写作。在缓冲区满之前,您的单线程不会阻塞。
      猜你喜欢
      • 1970-01-01
      • 2012-06-01
      • 2010-11-08
      • 2020-12-29
      • 2011-06-15
      • 2015-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多