0

我正在学习 PerfView 并尝试了 GCStats 报告。我创建了一个简单的应用程序,它在堆上做了很多内存分配:

using System;
using System.Collections.Generic;


class Program
{
    static void Main(string[] args)
    {
        GcReport();
        const int size = 10 * 1024 * 1024;
        var list = new List<int>();
        for (int i = 0; i < size; i++)
        {
            list.Add(i);
        }

        for (int i = 0; i < size; i++)
        {
            object obj1 = list[i];
            object obj2 = list[i];

            if (obj1 == obj2)
                Console.WriteLine("Match found");
        }

        GcReport();  // <-- results are shown below 
    }

    private static void GcReport()
    {
        Console.WriteLine($"Gen0: {GC.CollectionCount(0)}");
        Console.WriteLine($"Gen1: {GC.CollectionCount(1)}");
        Console.WriteLine($"Gen2: {GC.CollectionCount(2)}");
    }
}

以下是我在 PefrView 中配置“运行”对话框的方法:在此处输入图像描述

这是 PerfView 的 GCStats 报告: PerfView 的 GCStats 报告

这里是 PerfView 的日志文件,它显示了第二个 GcReport() 方法的结果: 在此处输入图像描述

如您所见,在 PerfView 的报告和控制台日志结果中,GC 收集的数量是不同的。有人可以解释一下,为什么数字不同?

4

1 回答 1

2

报告的主要区别在于 GCReport 显示每个 EXACTLY 代的数量,而 GC.CollectionCount 显示特定代的 GC 数量或更高。因此 GC.CollectionCount(0) 是 ALL GCS(即 Gen0,或 Gen1 或 Gen2),请注意它们在上面是一致的。

第 2 代的数量存在差异(如果输出显示第 2 代计数 = 3 而不是 4,则 PerfView 和计数将完全一致)。

这很容易成为一些“边界”问题(第 2 代开始但未完成)。在这一点上我只能推测。但是,如果您愿意,您可以准确地弄清楚这一点。创建一个 EventSource(请参阅我的博客文章“在 C# 中记录 ETW 事件:System.Diagnostics.Tracing.EventSource”)并在分配时频繁记录 GC 计数。然后,您可以查看“事件”视图并查看所有 GC 和 GCCount,您可以确定为什么会有任何差异。

于 2017-07-10T15:49:37.013 回答