为什么所有堆中的#字节都被认为是整个托管堆的良好衡量标准

时间:2015-11-13 15:00:17

标签: .net memory-management garbage-collection performancecounter

我正在使用性能计数器监视我的.NET应用程序高内存问题。为了测量.NET内存,我的印象是所有堆中的字节数性能计数器提供了整体托管内存使用量。但是根据MSDN,此计数器不包括Gen 0堆大小。

  

显示Gen 1堆大小,Gen 2堆大小和大的总和   对象堆大小计数器。此计数器指示当前内存   在垃圾收集堆上以字节为单位分配。

如果.NET应用程序在Gen 0中分配了大量内存,那么在所有堆中的#字节中也不应该考虑这个问题吗?我知道Gen 0堆大小有一个单独的计数器,但Gen 1,Gen 2和LoH也是如此。

2 个答案:

答案 0 :(得分:2)

这是相当主观的。但是当你问“我的.NET应用程序使用了多少内存”这个问题时,你通常不会对存在一毫秒或更短时间的内存分配感兴趣。可以这么说“工作记忆”。由存储在gen#0堆段中的对象类型使用。

只有当这些对象活得足够长,从而升级到更高代时,你才会开始担心你的应用可能没有高效地使用内存。永远不要担心第0代。

另一种实用性发挥作用的非零赔率。如果计数器也会显示第0代,那么这将是一个急剧变化的数字,它会迅速反复上下跳动。基本上是图中的白噪声,不是很友好。

答案 1 :(得分:1)

请注意" Gen 0堆大小"没有告诉你Gen 0堆中的对象占用了多少字节 - 它总是预先分配到一定的大小,并且在分配期间不会增长。这个数字只是告诉你为Gen 0分配预分配了多少内存。

实际上还没有一种实时方法可以获得第0代中对象的大小 - 它的流量有点过高而不值得。相比之下,Gen 1和Gen 2堆只能在垃圾收集期间填充 - 在那里设置性能计数器是微不足道的。 LOH也有类似的推理 - 你要分配足够大的对象,所以增加性能计数器的成本大多是微不足道的。

不要忘记Gen 0对象不能长时间停留在Gen 0中 - 在下一次收集过程中,他们要么被释放要么被移动到Gen 1.它''很难想象Gen 0堆的人口密集 - 事实上,IIRC,它相对于CPU缓存进行了缩放;虽然那不完全是"小"在现代CPU上,它也清楚地显示了它的意图 - 它是一本小书的临时书,几乎可以立即丢弃或移走。