为什么 # Bytes in all Heaps 被认为是衡量整体托管堆的好方法

Why # Bytes in all Heaps considered good measure for overall managed heap

我正在使用性能计数器监控我的 .NET 应用程序高内存问题。对于测量 .NET 内存,我的印象是 # Bytes in all Heaps 性能计数器提供总体托管内存使用情况。然而,根据 MSDN,此计数器不包括 Gen 0 堆大小。

Displays the sum of the Gen 1 Heap Size, Gen 2 Heap Size, and Large Object Heap Size counters. This counter indicates the current memory allocated in bytes on the garbage collection heaps.

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

这是相当主观的。但是,当您问 "how much memory does my .NET application use" 这个问题时,您通常对存活时间为一毫秒或更短的内存分配不感兴趣。 "working memory" 可以这么说。由存储在第 0 代堆段中的对象种类使用。

只有当这些对象存活得足够长,并因此被提升到更高的世代时,您才会开始担心您的应用可能没有有效地使用内存。永远不要担心第 0 代。

另一个实用性发挥作用的可能性非零。如果计数器也显示 gen #0,那么它将是一个变化很大的数字,会非常迅速地上下反弹。基本上是一张图中的白噪声,不是很友好

请注意,"Gen 0 Heap Size" 不会告诉您第 0 代堆中的对象占用了多少字节 - 它总是预先分配到特定大小,并且在分配期间不会增长。该数字只是告诉您为 Gen 0 分配预分配了多少内存。

在 Gen 0 中并没有真正实时的方法来获取对象的大小 - 它的流量有点太高了,不值得。相比之下,第 1 代和第 2 代堆只能在垃圾回收期间填充 - 在那里设置性能计数器是微不足道的。 LOH 有类似的推理 - 您正在分配足够大的对象,因此增加性能计数器的成本大部分是微不足道的。

不要忘记 Gen 0 对象不能在 Gen 0 中停留很长时间 - 在下一次回收期间,它们要么被释放,要么被移动到 Gen 1。很难想象一个场景Gen 0 堆被大量填充 - 事实上,IIRC,它是相对于 CPU 缓存缩放的;虽然这在现代 CPU 年代并不完全是 "small",但它也清楚地表明了意图 - 它是一些几乎立即被扔掉或搬走的小物件的便签本。