垃圾收集
垃圾收集 过滤器用于通过筛选执行 GC 的时间间隔来分析垃圾回收 (GC)。
要了解 垃圾收集 过滤器的工作原理,您需要熟悉基本的 GC 概念。
简要介绍垃圾回收概念
对于桌面应用程序,.NET Framework 提供了一种所谓的工作站 GC 模式。
工作站垃圾回收有两种类型:前台和后台。
执行前台 GC 时,垃圾回收器会挂起除触发回收的线程以外的所有托管线程。 这也会挂起主线程并导致 UI 冻结。 这是一个“纯粹的” 阻塞 GC。
后台 GC 由单独的 GC 线程执行,并且在执行“最重的” Gen2 回收时不会挂起托管线程。 然而,在 Gen0 和 Gen1 回收期间,托管线程仍然需要被挂起。 因此,后台 GC 仍然涉及短暂的“阻塞 GC”间隔。 默认情况下,后台 GC 是启用的。
对于服务器应用程序,有一种特殊的服务器 GC 模式。 与工作站 GC 相比,服务器 GC 模式的主要区别在于每个逻辑处理器都有自己的托管堆和单独的 GC 线程。 从 dotTrace Viewer 的性能分析角度来看,后台 GC 和服务器 GC 之间没有显著差异。
在 Microsoft Learn 中了解更多关于 GC 类型的信息。
为了帮助您区分何时执行特定类型的 GC,dotTrace 为您提供了 垃圾回收:类型 子过滤器。
垃圾回收:类型
子过滤器显示特定类型回收的总 GC 时间分布。
使用此子过滤器分析垃圾回收:原因、线程和触发回收的方法。 例如,如果您看到显著的阻塞 GC 时间,建议切换 事件 过滤器到 .NET 内存分配 ,并确定分配内存最多的线程。 这些线程很可能是触发 GC 的线程。

GC 类型:
阻塞 - 阻塞垃圾回收。 除触发 GC 的线程外,所有线程都会被挂起。 您分析的主要对象。
背景 - 由单独的 GC 线程执行,并且在执行“最重的” Gen2 回收时不会挂起托管线程。 过多的后台 GC 也是优化的对象。
后台期间阻塞 - 后台 GC 在 Gen2 回收期间不会挂起其他线程。 然而,Gen0 和 Gen1 回收(作为完整 GC 的不可避免部分)仍然需要挂起托管线程。 因此,后台 GC 始终意味着短暂的阻塞 GC 间隔。 后台期间阻塞 类型将过滤掉这些间隔。
对应类型的 GC 所花费的总时间,汇总所有选定线程。
对应类型的 GC 所花费时间占所选总时间的百分比。
应用垃圾回收:类型过滤器
在过滤器中选择所需的 GC 类型。
选择 GC 类型后,其他过滤器将仅显示在所选类型的 GC 执行的时间间隔内的数据。

为了更好地理解 dotTrace 如何计算垃圾回收间隔,请参考以下示例。
示例
例如,您的应用程序有两个线程:User Thread#1 和 User Thread#2。 在某个时刻,为释放一些内存,User Thread#1 触发了阻塞的 Gen0 和 Gen1 垃圾回收(下图中的 A1 间隔)。 由于内存仍然不足,创建了一个 GC 线程。 它执行了完整的 GC,包括 Gen0 和 Gen1 的阻塞回收(C3 )以及 Gen2 的回收(B3 和 D3 ),后者不会阻塞其他线程。

如果您在 线程 图表上选择所有三个线程,过滤器将按以下方式计算 GC 时间:
垃圾回收 = A1 + B3 + C3 + D3
垃圾回收:阻塞 = A1 + C3
垃圾回收:后台 = B3 + C3 + D3
垃圾回收:后台期间的阻塞 = C3
请注意,除了 垃圾收集 事件外,您还可以在 子系统中使用 GC 等待 子系统来评估所选时间间隔内的垃圾回收量。 不要被显示在 垃圾收集 和 GC 等待 中的不同时间值所迷惑。 原因是, 垃圾收集 仅计算实际执行 GC 的线程,而 GC 等待 子系统时间包括所有被 GC 阻塞的线程的等待时间。 根据上述示例, GC 等待 将按以下方式计算:
GC 等待 = A1 + A2 + C1 + C2 + C3
垃圾回收:深度
垃圾回收:深度 子过滤器显示 Gen0、Gen1 和 Gen2 堆回收之间的 GC 时间分布。
请注意,Gen1 回收总是意味着同时回收 Gen0 堆段。 Gen2 GC(也称为完整 GC)包括 Gen1 和 Gen0 的回收。 因此,在 Gen1 回收中执行 Gen0 回收所用的时间将被汇总到 Gen1 GC 时间中。 Gen2 GC 时间将包括其触发的 Gen0 和 Gen1 回收的时间。

堆段名称。
对应深度的阻塞 GC 所花费的总时间,汇总所有选定线程。
对应深度的阻塞 GC 所花费时间占所选总时间的百分比。
应用垃圾回收:深度过滤器
在过滤器中选择所需的堆段名称。
选择堆段后,其他过滤器将仅显示在所选深度的 GC 执行的时间间隔内的数据。
