【问题标题】:Server Garbage Collection & linear increase in parallel task times服务器垃圾收集和并行任务时间的线性增加
【发布时间】:2011-03-16 18:12:55
【问题描述】:

伙计们 - 我有一个任务 A,我按顺序执行了大约 100 次。每个任务 A 都有许多并行处理的任务 B。 B 存储所有 A 完成后所需的数据。所以程序的内存占用会随着时间的推移而增长。这些是“长期运行”的任务。

我发现 A 需要很长时间才能完成每个连续的 A。我实施了服务器垃圾收集并且有显着的改进 - A 的完成时间减少了一半!然而,A 的完成时间仍然随着每个连续的 A 线性增长。所以到了第 10 个 A,服务器垃圾收集的改进已经无关紧要 - 完整的 100 个 A 永远不会在合理的时间内完成,我需要停止这个过程。

我的假设是,不断增长的内存占用会导致 GC 随着时间的推移做更多的工作,从而减慢一切。

  1. 您还有其他假设可以检验吗?
  2. 如果我的假设值得探索,我可以寻求哪些解决方案?我应该更加“亲力亲为”地使用垃圾收集器吗?也许我应该将内存中的数据刷新到磁盘并在需要时将其吸收?

编辑
我忘了提到每个 B 调用 GC.Collect 和 GC.WaitForPendingFinalizers 因为我正在自动化 COM,这是确保释放 COM 服务器进程的唯一方法。

【问题讨论】:

  • .net 有一个堆分析器 (CLRProfiler),您可以使用它来找出哪些数据是实时的以及哪些数据持有指向它们的指针。我没有使用 .net 的经验,但 Haskell 中的堆分析器帮助我找到了与 GC 相关的内存泄漏。
  • 我不担心泄漏...内存占用量的增长是预期的。正如我所说,“B 存储所有 A 完成后所需的数据”
  • 听起来像是正常的 OutOfMemory-Situation 由于泄漏或只是太多的数据。在 OutOfMemory 附近,GC 反复尝试释放内存并失败 -> CPU 正忙于垃圾收集。这需要一些时间才能引发 OutOfMemoryExceptions。
  • 我几乎没有内存不足。我在内存中使用 6gb,我还剩下将近 9gb (x64)。也没有内存泄漏。
  • 为什么不用Dispose 摆脱原生资源呢?调用 GC.Collect 通常是错误的。

标签: .net .net-4.0 garbage-collection task-parallel-library


【解决方案1】:

找到问题了!当每个 A 完成时,我现在将数据序列化到磁盘。这样,内存占用在 A 上是恒定的。使用这种技术,完成 A 所需的时间不再呈线性增长。它是常数。完成所有 A 后,我只需反序列化磁盘上的数据。虽然这有点费时,因为现在有很多数据要读取,但它不应该与保持 A 保持恒定时间所节省的时间相比。

【讨论】:

  • 你可以只使用 MemoryStream。
【解决方案2】:

如果你真的懒得清理你的 COM 东西,我会使用一个 AppDomain 来进行 COM-Interop,另一个来积累数据。

【讨论】:

  • 它与干净地处理 COM 无关。阅读任何有关 Excel 自动化的文章。你必须调用 GC.Collect。没有办法解决它。
  • 除非你做 AppDomain 的事情......但这不是处理 Excel 时的常见模式。
猜你喜欢
  • 2018-01-28
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 2012-06-28
  • 2010-12-15
  • 2013-08-08
相关资源
最近更新 更多