计算排队等待垃圾回收的总对象

时间:2015-06-14 05:09:53

标签: c# garbage-collection

我想在我的OpenGL游戏中添加一个小的调试UI,它将经常使用各种调试选项/输出显示进行更新。我想要的一件事是一个常量计数器,它在每一代垃圾收集器中显示活动对象。我不想要名字或任何东西,只是总数;当我在游戏中做某些事情时,我可以注意一些事情。

然而,我的问题是,我似乎找不到计算各代人目前活着的总物品的方法。

我甚至考虑过保留一个全局静态字段,它将在每个构造函数中递增并在类终结器中递减。这需要将所述功能手动编码到每个类中,并且不能解决“每代总计”的问题。

你知道我该怎么做吗?

2 个答案:

答案 0 :(得分:3)

  

(问题标题:) “计算排队等待垃圾收集的总对象”

     

(来自问题的主体:) “然而,我的问题是我似乎无法找到计算各代人目前活着的总物品的方法。

备注:您的问题的标题和正文要求相反的事情。在标题中,您要求通过任何GC根目录无法再访问的对象数量,而在正文中,您要求“实时”对象,即仍可通过任何GC根目录访问的对象

首先我要说可能没有办法做到这一点,主要是因为.NET中的对象不是引用计数,所以它们不能立即标记为“不再需要”当最后一次引用它们消失或超出范围时。我相信.NET的mark-and-compact垃圾收集器只能发现哪些对象是活着的,哪些对象可以在实际的垃圾收集过程中回收(在“标记”阶段)。但是,您似乎需要提前 ,即在GC发生之前。

话虽如此,这可能是您最好的选择:

  1. 也许您在.NET的托管框架类库中最好的选择是 performance counters 。但它看起来没有任何合适的计数器可用:有各种性能计数器为您提供各代GC生成的已分配字节数,但AFAIK没有计数活动/死对象的数量。

  2. 可能也想看看 CLR(即运行时)的非托管,基于COM的Debugging API 。鉴于您已检索到ICorDebugProcess5 interface,可能会对这些方法感兴趣:

      

    “获取要在进程中进行垃圾回收的所有对象的枚举器。”

    另请参阅this answera similar question on SO

    请注意,这是关于要进行垃圾收集的对象,而不是关于活动对象。

      

    “提供有关垃圾收集堆的一般信息,包括它当前是否可枚举。”

    如果事实证明托管堆 是可枚举的,您可以使用...

      

    “获取托管堆上对象的枚举器。”

    此枚举器返回的对象属于以下类型:

      

    “提供有关托管堆上对象的信息。”

    您可能实际上对这些细节不感兴趣,只是对枚举器返回的对象数量感兴趣。

    (我自己没有使用过这个API,也许存在一种更好,更有效的方式。)

  3. 2015年9月,Microsoft发布了一个名为clrmd aka Microsoft.Diagnostics.Runtime on GitHub的托管库。它基于与上面提到的非托管调试API相同的基础。该项目包括documentation about enumerating objects in the GC heap

  4. 顺便说一下。 Ben Watson "Writing High-Performance .NET Code"提供了一本内容非常丰富的书,其中包含有关如何使.NET内存分配和GC更高效的实用技巧。

答案 1 :(得分:1)

垃圾收集器不必收集对象。

  

......垃圾收集器会发现这个事实   为对象所在的任何一代运行收集器。(如果它   完全运行,它可能不会。 There is no guarantee that the GC   运行。)

     

(C)Eric Lippert

如果应用程序正常运行且内存消耗没有增加,GC可以让它在不中断的情况下运行。这意味着数字因运行而不同。

如果我是你,我不会花时间来获取世代信息,而只是用尽内存的大小。

简单但不太准确的方法是从GC获取它。

    // Determine the best available approximation of the number  
    // of bytes currently allocated in managed memory.
    Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));

如果您看到使用的内存经常增加和减少,那么您可以使用现有的分析器来确定您分配的位置过多,甚至是内存泄漏的位置。