【发布时间】:2011-03-16 18:12:55
【问题描述】:
伙计们 - 我有一个任务 A,我按顺序执行了大约 100 次。每个任务 A 都有许多并行处理的任务 B。 B 存储所有 A 完成后所需的数据。所以程序的内存占用会随着时间的推移而增长。这些是“长期运行”的任务。
我发现 A 需要很长时间才能完成每个连续的 A。我实施了服务器垃圾收集并且有显着的改进 - A 的完成时间减少了一半!然而,A 的完成时间仍然随着每个连续的 A 线性增长。所以到了第 10 个 A,服务器垃圾收集的改进已经无关紧要 - 完整的 100 个 A 永远不会在合理的时间内完成,我需要停止这个过程。
我的假设是,不断增长的内存占用会导致 GC 随着时间的推移做更多的工作,从而减慢一切。
- 您还有其他假设可以检验吗?
- 如果我的假设值得探索,我可以寻求哪些解决方案?我应该更加“亲力亲为”地使用垃圾收集器吗?也许我应该将内存中的数据刷新到磁盘并在需要时将其吸收?
编辑
我忘了提到每个 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