如何使用大文件I / O(读,写)和计算优化例程?

时间:2012-04-17 21:26:48

标签: c# performance .net-4.0

我知道他们说过早优化是所有邪恶的根源......但那是关于那段时间。

我有一个缓慢但有效的工作程序,可执行以下操作:

  1. 从file.input
  2. 读取chunk(顺序)
  3. 转换块
  4. 将已转换的块写入(附加)到file.output
  5. file.input和file.output最终处于相同大小的球场(10-100 + GB)。块通常约为10K。转换步骤只是专有格式之间的转换。为了便于讨论,我们可以认为它与计算上的实时压缩算法相同。

    这些步骤目前在一个线程中完成。

    我的问题:如何让这个表现更好?

    我意识到基于正在处理的纯数据量,这将永远不会“快速”,但我不得不相信有一些相对简单和标准的技术可以更快地实现这一点。

    我已尝试在阅读步骤(1)中添加缓冲。也就是说,读取比块大小更大的块并从缓冲区读取。这有帮助。但是,如果对转换步骤(2)和追加(3)有任何可以做的事情,我会有点卡住。

    根据资源监视器,我的CPU使用率在30-45%之间波动,而磁盘I / O有一些持续的低使用率。

    我正在使用C#和一堆P / invoke互操作到本机库。

5 个答案:

答案 0 :(得分:2)

首先,你应该确认所有步骤都花费了大部分时间 - 如果瓶颈只是一步,我们在这里看错了。

磁盘I / O可能需要一段时间才能用于其他任务,因此多线程解决方案可以提高性能。也许您可以使用一个线程来保持缓冲区最多10个可处理数据块,一个处理第一个块加载的块,另一个块只写入已完成处理的任何块。然后,一对AutoResetEvents可以通知每个线程前一个线程已经完成处理一个或多个块。

答案 1 :(得分:2)

首先,不要为这种情况添加线程,他们不会做任何事情来改善你的表现。 (当然,如果您的应用程序具有UI界面,您可以添加一个线程来执行密集型工作,并让用户继续执行其他任务)

其次,尝试最小化磁盘上的IO。尽可能多地读取字节并写入所有togheter。 第三,最好的办法是优化转型工作。

答案 2 :(得分:1)

如果您使用的是.NET 4,则可以尝试MemoryMappedFileMemoryMappedViewAccessor

答案 3 :(得分:1)

测量

  • 1(简单顺序读取到无处),
  • 3(随机字节的简单顺序写入)
  • 1 + 3(读取并立即复制到尺寸合理的块16K-64k-512k-1Mb)
  • 2(只是计算)

比看你的数字,看看重叠是否会带来任何可观的好处。 45%的CPU负载并不算太差,所以你可能会保持原样。

你能得到的最好是Max(1,2,3),所以要相应地计划优化。

答案 4 :(得分:1)

您的主要问题是I / O.你在两个文件之间交替使事情变得更糟的事实。

  • 缓冲读写。大动作更好,在这种情况下,更少的动作也更好。

由于还有CPU密集型部分,我会尝试使用线程。为了减少等待,我将使用管道:ReaderThread - >队列 - > ProcescessingThread - >队列 - > WriterThread