【问题标题】:Determine memory usage of object graph in .NET确定 .NET 中对象图的内存使用情况
【发布时间】:2014-12-03 10:47:43
【问题描述】:

部分是出于好奇 - 我们想知道我们的应用程序中发生了什么 - 部分是因为我们需要在我们的代码中找到一些潜在的问题,我喜欢在我们的 Web 应用程序运行时跟踪一些一般值。这尤其包括某些对象图的分配内存。

我们的应用程序将一些数据永久保存在内存中,以使其可靠可用。这可以总计达到几 GB 的内存,而执行几乎相同任务的其他应用程序只分配一两个。

由于性能要求,我们无法在运行时附加内存分析器。 因此,在运行时分析对象图以打印出数据的哪些部分在某些情况下如此之大以及哪些部分不是那么大,这将是很棒的。这将极大地帮助我们更好地了解数据会发生什么,并可能优化我们的应用程序的行为。

对象图的意思是,从一个某个对象开始,测量它在内存中的大小,通过所有属性、字段、列表及其所有元素等递归地跟踪所有引用的对象,并添加它们相应的大小,直到我们知道这个对象和所有相关对象使用了多少内存。

实际上,我想回答的问题是:当我刚刚释放对这个锚对象的最后一个引用时,GC 在下次运行清理这个对象图时能够释放多少?

【问题讨论】:

    标签: .net memory memory-management


    【解决方案1】:

    不清楚这是否满足您的要求,但 Windbg 的 SOS 扩展提供了!objsize 命令以递归方式确定对象的大小,包括所有引用的对象。您可以附加到正在运行的进程,或者进行内存转储(例如使用procdump),然后附加到转储文件以离线执行分析。然而,!objdump 的输出只会是您最后一个问题的答案,如果子对象 only 可以从您的初始对象访问(任何其他引用当然会阻止子对象树即使您的初始对象变得无法访问,也会被收集)。

    从进程本身来说这如此困难的部分原因是运行时必然隐藏了很多关于内存表示的细节。其中一些可以通过使用不安全的代码来克服,但它仍然不是微不足道的,因此在 Windbg 中使用诸如“了解”CLR 内部的 SOS 之类的东西可以使该过程变得更加容易,但明显的限制是它必须从流程“外部”完成,而不是从内部完成。

    【讨论】:

      【解决方案2】:

      如果您不使用分析器,您将面临一项艰巨的任务。

      关于测量对象图大小的问题已在 SO 上多次提出,例如:

      Ways to determine size of complex object in .NET?

      How to get object size in memory?

      每个问题都收到了一堆答案(请随意阅读它们),但老实说,它们或多或少都很糟糕。您必须接受没有可靠的方法来获取此信息,因为它是一个实现细节。

      但是让我们假设您真正需要的不是准确的测量值,而是一些大致数字来了解“大男孩对象”在哪里。

      • 序列化您的对象图

      我能想到的一种简单方法是使用二进制格式化程序将对象序列化到内存流中并检查其大小。

      • 使用转储文件

      另一种方法是创建应用程序的转储文件并使用它们来分析内存。 Visual Studio 2013 有一个新的内存分析器,可帮助您从生产机器上收集的 .dmp 文件了解应用程序的 .NET 内存使用情况。

      它还会显示所有对象的大小:

      对此有两部分的介绍:

      第 1 部分: http://blogs.msdn.com/b/visualstudioalm/archive/2013/06/20/using-visual-studio-2013-to-diagnose-net-memory-issues-in-production.aspx

      第 2 部分: http://blogs.msdn.com/b/visualstudioalm/archive/2013/10/16/net-memory-analysis-enhancements-in-visual-studio-2013.aspx

      • 使用 Microsoft.Diagnostics.Runtime "CLR MD"

      CLR MD 是一个用于构建诊断工具的 C# API。它为您提供了 SOS 和 PSSCOR 调试器扩展可以在简单、快速的 C# API 中执行的功能和灵活性。

      github 上的文档有一个关于非线性堆遍历器的示例,用于计算对象的大小。它的工作原理与 SOS 中的 !objsize 相同,因此该命令将对象作为(参数并计算它保持活动状态的对象数量以及报告(给定对象保持活动状态的所有对象的总大小。

      https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/docs/WalkingTheHeap.md

      【讨论】:

      • 令我困惑的是:内存分析器如何获取这些信息?在同一个流程中,这应该更有可能。
      猜你喜欢
      • 2010-11-26
      • 2011-11-02
      • 2010-09-28
      • 2011-06-15
      • 2010-10-08
      • 2014-07-30
      • 2012-08-27
      • 2012-01-13
      相关资源
      最近更新 更多