【问题标题】:Long running simulation app on .NET CLR.NET CLR 上长时间运行的模拟应用程序
【发布时间】:2012-09-28 14:43:43
【问题描述】:

我们编写了一个应用程序,该应用程序是一个需要 24 小时不间断运行的数字运算模拟。 它使用窗口形式的绘画事件来连续呈现主题的视觉表示,另外我们使用几个实时图形和网格来显示项目对象的进度。它是一个 .NET Windows 窗体应用程序。

4 小时后,我们得到 System outOfMemory 异常。

Memory Profiler 告诉我们,如果我们权衡一些实时图表和其他一些未处理的对象,我们可以节省“一些”(35%-40%) 内存。

我担心它仍然不会 24 小时不间断运行。我们的 HP 8440p Elitebook Intel i5 已经安装了 32 位 Win7 的 4GB RAM。

我们的目标是为我们的模拟应用程序和运行它的 .NET CLR 提供尽可能多的内存。 投资更多内存(可能是 8GB)和 64 位操作系统会有帮助吗?除了添加更多硬件之外,我还需要考虑哪些其他可能的 CLR 选项?

非常感谢。

【问题讨论】:

  • 如果你有一些生命周期很短的对象,像一个较长生命周期的对象的注册事件会让它们活着。您是否订阅了活动但没有取消订阅?在我看来,这听起来像是一堆你认为已经死了但实际上并没有死的物体。
  • 它实际上是保存图形绘图点的大数组的累积。我们正在添加当前值,并删除和处理旧值,但它是最大的内存消耗部分。
  • 你知道阵列能有多大吗?此外,绘图点实例或其子对象/属性之一的长度是否超过 85,000 字节?

标签: .net memory clr


【解决方案1】:

@Adam Houldsworth 的建议非常好。您可能会面临内存泄漏(对过时对象的引用仍然被保留,正如 Adam 建议的那样,通过实时事件订阅非常频繁,这可以防止它们被垃圾收集)。

@mkimes 的回答也很有价值。实际上,作为 64 位进程运行将允许您的应用程序管理更多内存,但仍然存在一些警告(例如单个对象大小的 2GB 限制)。

如果您直觉地认为应用程序不应该耗尽内存,因为根据您的推理,大多数创建的对象都是短暂的并且应该被释放,那么您可能正面临内存泄漏。但是,如果进程正在构建大量对象,这些对象在进程完成后或在较长的计算阶段期间应该保持活动状态,那么您可能会遇到 32 位内存限制障碍,特别是考虑到在一个完整的垃圾回收周期,应用程序的内存将趋于临时增长接近当前分配大小的两倍,将实际的 32 位内存大小限制保持在 1GB 左右。

有一个Windows configuration switch 允许将 32 位应用程序可以处理的内存大小增加到 3GB,但是根据我的经验,这会使操作系统不稳定(非常频繁的蓝屏),因此请谨慎探索此选项。

如果您怀疑内存泄漏:

这个article 可能会有所帮助,它向您展示了如何使用 Windgb(一种高级调试器)来跟踪可能使不需要的、过时的引用保持活动状态的对象。

另外(希望不是),您可能会成为一个非常讨厌的问题的受害者,即内存碎片可能由 CLR 认为的“大对象”的重复、频繁分配引起,即大于 85,000 字节的对象尺寸。这是article 详细说明问题。基本上,这些对象被分配在不同的堆下,但不幸的是,从未压缩过。这意味着释放的内存块将散布在分配的块中,并且运行时可能在某些时候找不到单个连续的内存块来满足内存请求,从而触发内存不足异常。如果是这种情况,将一个大的、整体的对象分解成更小的对象会有所帮助。

最后,任何对象的大小都不能大于 2GB即使在 64 位以下,所以您必须注意您的集合和/或数组未达到此限制。

【讨论】:

  • 肯定有内存泄漏。我们严格执行的第一条规则是使用“using”表达式正确调用 System.Drawing 命名空间。
  • 发现这个非常有趣的 SO question 可能适用于您的情况,因为您使用的是 Windows 窗体。请关注该问题的公认答案以及已知会泄漏内存的 Windows 窗体使用模式的描述。祝你好运!
【解决方案2】:

应用程序是 64 位的,在 64 位操作系统上运行吗? 32 位 CLR 应用程序的上限非常低(远低于 2GB 逻辑限制) - 但 64 位 CLR 应用程序应该能够毫无问题地使用大量内存。当物理内存用完时,64 位应用程序也将分页到磁盘 - 因此整个机器将用完物理内存并在您从 CLR 收到 OutOfMemory 错误之前很久就开始分页到磁盘。

【讨论】:

  • 不,它是一个 32 位应用程序,目前在 32 位操作系统上运行。
猜你喜欢
  • 1970-01-01
  • 2018-02-24
  • 2011-05-20
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多