2014-10-08 40 views
3

部分出于好奇 - 我们想知道我们的应用程序中发生了什么 - 部分原因是我们需要在代码中发现一些潜在的问题,我喜欢在运行时跟踪一些常规值我们的网络应用程序。这尤其包括某些对象图的分配内存。确定.NET中对象图的内存使用情况

我们的应用程序会将一些数据永久保留在内存中以使其可靠可用。这可以总结为几GB的内存,而做几乎相同的东西的其他应用程序只分配一个或两个。

由于要求的性能,我们无法在运行时连接内存分析器。 因此,在运行时分析一个对象图很好,可以打印出哪些部分的数据在某些情况下非常大,哪些不那么大。这将有助于我们更好地理解数据会发生什么并可能优化应用程序的行为。

对象图的装置,从一定对象开始,测量其在存储器大小,递归地跟踪通过所有属性,字段,列表与他们的所有元素等所有引用的对象和加入它们的相应尺寸,直到我们具有信息该对象和所有相关对象使用了多少内存。

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

回答

3

如果您没有使用探查器,您将面临艰巨的任务。

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

Ways to determine size of complex object in .NET?

How to get object size in memory?

每个问题已收到一堆答案(随意通读他们),但说实话,他们都吸或多或少。您必须接受没有可靠的方式来获取这些信息,因为它是一个实现细节。

但让我们假设你实际需要的不是一个准确的测量,而是一些球场数字来知道“大男孩物体”在哪里。

  • 您的序列化对象图

一个简单的方法我能想到的是用二进制格式序列化你的对象到内存流和检查的大小。

  • 使用转储文件

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

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

enter image description here

有两个部分介绍了这个:

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上的文档有一个关于用于计算对象大小的非线性堆栈walker的示例。它与SOS中的!objsize相同,因此该命令将一个对象作为参数并计数它保持活动的对象的数量以及报告(给定对象保持活动状态的所有对象的总大小)

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

+0

这是什么让我感到困惑:内存分析器如何获取这些信息?这应该在同一过程中更有可能。 – 2014-10-08 18:41:22

1

目前尚不清楚这是否符合您的要求,但SOS扩展WinDBG的提供!objsize命令,以确定一个对象递归包括所有引用的对象的大小。您可以附加到正在运行的进程,或采取内存转储(例如,使用procdump),然后附加到转储文件以脱机执行分析。但!objdump的输出只会是最终问题的答案,如果子对象只有可从初始对象到达(任何其他引用当然会阻止即使您的初始对象无法访问也收集子对象树)。

从流程本身来看,这很困难的原因部分是由于运行时必然会隐藏很多关于内存表示的细节。其中一些可以通过使用不安全的代码来克服,但它仍然是非常重要的,所以在Windbg中使用类似SOS的东西可以“知道”CLR的内部结构,这使得过程变得更加容易,它必须从过程的“外部”完成,而不是从内部完成。