【问题标题】:.NET WinForm Memory Consumption.NET WinForm 内存消耗
【发布时间】:2011-04-19 20:53:12
【问题描述】:

我一直在使用“.NET Memory Profiler”分析 WinForm 的应用程序。

我似乎不太明白我的应用程序是如何增长到 1GB,然后是 2GB,然后是 3GB 的使用量 - 根据 Windows 任务管理器。

使用该工具的私有字节数和“所有堆中的总字节数”仅显示为 70MB 左右。在我的实例列表的顶部,它们主要是字符串,或者是对许多小对象的弱引用。

应用程序所做的只是显示一个从数据库加载数据的表单。我重复表单的显示/处理循环大约 100 次,并且增长是连续的。

我现在已经尝试了大约 3 种内存分析工具,但没有一个能告诉我这么大的内存消耗来自哪里。

谁能帮忙或猜猜它可能是什么?

谢谢。

【问题讨论】:

  • 您是从 IDE 分析可执行文件还是调试版本?
  • 我正在分析在调试模式下构建的 EXE,而不是通过 IDE。
  • 这真的是用vb.net写的app吗?那么 WeakReference 泄漏是预期的。
  • 是的,基于 .NET 2.0 的 VB .NET 应用程序。
  • @Hans Passant。这是 VB.NET 应用程序的已知问题吗?有文章链接吗?

标签: vb.net winforms memory


【解决方案1】:

这是 VB.NET 应用程序的已知问题吗?

是的。这是编译到可执行文件中的 Edit + Continue 支持的副作用。它受到使用 WithEvents 关键字声明的任何事件的影响。 WeakReference 跟踪这些事件实例。问题是,如果您在没有调试器的情况下运行应用程序,这些 WeakReferences 就会泄露。进程消耗内存的速度很大程度上取决于创建了多少类实例。泄漏是每个对象每个事件 16 个字节。

解决方法很简单,不要在没有调试器的情况下使用应用的调试版本。仅使用发布版本。当然,只向您的客户发送 Release 版本。

【讨论】:

  • +1。这是相关Microsoft KnowledgeBase article 的链接,只是为了完整起见。汉斯的回答并没有增加任何内容
  • 您可能知道,在发布版本中,不会发出符号调试信息,并且优化了代码执行,因此最终可执行文件的大小小于调试可执行文件。但是,首先检查您在调试和发布配置中指定的设置(如何发出符号调试信息)(右键单击您的 win 表单项目 -> 属性 -> 构建选项卡 -> 高级... -> 调试信息设置),然后想想你想让他们成为什么样的人。
【解决方案2】:

我似乎不太明白我的应用程序是如何增长到 1GB,然后是 2GB,然后是 3GB 的使用量 - 根据 Windows 任务管理器。

这是因为任务管理器的计数器是 Tess Ferrandez 在this article 中指出的“工作集”

还有一个计数器叫做 简化的工作集包括 内存中有多少内存 当前或曾经的页面 最近被线程中的 过程或大约,多少 进程使用的内存 当前在 RAM 中。工作集 计数器可能会很有趣,如果你 分页过多的问题和 许多进程在同一个盒子上 争夺内存,但为了 确定你有多少内存 使用(保留或承诺)它 提供很少或根本没有帮助。

来自工作集上的MSDN article(重点是我的)

工作集

内存页集 (分配给 a 的内存区域 进程)最近被线程使用 在一个过程中。如果可用内存打开 服务器高于指定的 阈值,页面保留在进程的工作集中,即使它们没有被使用。当可用内存下降时 低于指定阈值,页面是 从工作集中删除。如果这些 需要页面,它们将是 返回工作集 在他们离开主内存之前 可用于其他进程 使用。

【讨论】:

  • 感谢康拉德。我无法理解的是,当 Windows 仅在最大 3GB 的 RAM 盒上运行时,它是如何允许它消耗这么多 RAM 的。随着 Visual Studio 的打开和许多其他事情的发生,它肯定会溢出可用 RAM 的数量。我从未在非托管语言中看到过这种行为,这肯定是不合理的吗?运行几天的 Visual Studio 平均只消耗 400mb。
  • @MeshMan 我的猜测是您没有任何其他进程竞争 RAM,因此它不会修剪工作集并且您可能有一个非常大的页面文件
【解决方案3】:

我发现在 CPU 负载较高的情况下,垃圾收集通常获得非常低的优先级,因此负责清理未使用内存的 .NET 库只会在绝对必要时才会启动,尽管对 a 的引用计数托管对象变为零。如果有可能尝试在您的代码中添加一些有意的 Thread.Sleep 调用,只需接受它是内存占用的事实,并希望逻辑将允许您的系统运行并且它将具有“奇数”内存用法,因为您从未说过任何东西都会中断,它只是占用了不真实的内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-07
    • 2010-10-12
    • 1970-01-01
    • 2011-10-03
    • 2012-11-24
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多