【问题标题】:Writing files efficiently — Collect or write immediately高效写入文件——立即收集或写入
【发布时间】:2016-03-02 19:57:10
【问题描述】:

以下两种方法在文件 I/O 方面是否存在性能差异?

  • 使用由生产者填充的队列,并在所有数据到达后启动写入磁盘的任务
  • 让任务与生产者并行写入磁盘

数据被写入不同的文件和多个目录。 I/O 和 Parallel.ForEach 的单独任务将在这两种情况下使用。

我认为第二个版本的性能会更好,理论上生产者和 I/O 确实是并发的。由于 I/O 会导致调用进程中断,我想知道是否会有不利的一面。这可能会导致开销超过并行性的好处。

在某些情况下我应该支持第一个解决方案而不是第二个解决方案吗?

【问题讨论】:

  • 试试看。这是唯一确定的方法。我猜想通常并行化磁盘 IO 可能不会带来显着的好处,因为操作系统已经倾向于在幕后进行大量缓存。
  • 双向编写代码,拿出秒表,你就会知道答案。其他一切都在猜测。

标签: c# file io task parallel.foreach


【解决方案1】:

我认为第二个版本会更好

如果多个目录仍位于同一物理驱动器上,则使用第二个选项可能会获得更差的性能。

在某些极端情况下,并行编写(并将自己限制为仅 2 或 3 个线程)可以更快。例如,由于创建文件的开销成本超过了写入文件的 IO 成本,因此写入 1000 个 1kb 的文件在稍微并行的情况下会表现得更好。但是,如果您要编写 1000 个 1mb 的文件,那么使用单个线程进行写入可能会更快。

实现这一点的简单方法是使用TPL Dataflow,您可以拥有一个高度并行的TransformBlock,然后将其连接到执行写入的1 或2 线程ActionBlock。然后在设置链接时限制ActionBlock 的输入缓冲区,如果管道已满而不占用大量内存,TransformBlock 将阻塞生产者。

【讨论】:

  • 那么从一个同时运行的单独任务到生产者的顺序写入将是一个好方法吗?这将带来立即写入文件的好处,并且不会产生太多开销。
  • 如果我理解你在说什么,是的。实现这一点的一种简单方法是使用TPL Dataflow,您可以拥有高度并行的TransformBlock,然后将其连接到执行写入的1 或2 线程ActionBlock。然后在设置链接时限制ActionBlock 的输入缓冲区,如果管道已满而不占用大量内存,TransformBlock 将阻止生产者。
  • 如果你想看到这个过程的人为例子,请参阅我的this old answer,我传入一个文件路径,使用单线程异步加载图像,使用 5 同步裁剪图像并发线程,然后使用单个线程异步保存图像。
  • 谢谢!如果我不使用 async/await,这是否也有意义(对不起,如果这是一个新手问题)?
  • 不使用没有错。我只是使用它,因为 async/await 对 I/O 有意义。只需确保您使用的是同步方法,例如使用.Post( 而不是.SendAsync(,而不仅仅是调用带有.Wait().Result 的asnyc 方法。
【解决方案2】:

我不确定你所说的第二个任务是什么意思。我认为您正在谈论使用某种并发队列以及为其提供服务的消费者线程。生产者写入该队列。消费者线程等待信息被添加到队列中,并将该信息写入磁盘。这样,消费者可以在生产者处理并将内容添加到队列时写入磁盘。无需等待所有信息到达。

我在使用BlockingCollection 处理此类事情方面取得了很大成功。

如果这就是您所说的,那么它应该比您的第一个选项执行得更好,因为正如您所说,磁盘 I/O 线程和生产者线程是同时执行的。

【讨论】:

  • 是的,这正是我的意思,我也会使用 BlockingCollection。 Scott Chamberlain 的回答让我思考是否应该使用任务写入磁盘并按顺序浏览数据,还是在任务中使用类似 parallel.foreach 的东西。
  • 使用 I/OI find TPL Dataflow 很好用,它允许您使用异步 I/O 方法并处理管理 BlockingCollectionTasks 填充的所有工作或清空集合。
  • @John:我同意 Scott 的回答:让多个线程执行磁盘 I/O 可能不是一个好主意。
  • @JimMischel 好的。仍然想知道为什么 SO 上的许多答案都建议类似于 stackoverflow.com/questions/8505815/… ,如果我理解正确的话,它会为 I/O 创建多个任务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
相关资源
最近更新 更多