我在 netcore 2.2 上偶尔看到一个问题,其中并发 Gen2 GC 似乎不在后台 GC 线程上运行,而是在触发收集的线程上运行。
这是在我的 Windows 10 开发中观察到的,在 64 位 .NET Core 2.2 运行时使用默认 GC 配置文件(工作站、启用并发 GC、交互式延迟模式)以 Release 配置运行应用程序,并且我能够获取 perfview 示例发生的:
翻看GC源码,我觉得这个commit可能引入了一个问题。 在更改之前, bgc_thread
将在线程创建时设置,并保证在void gc_heap::garbage_collect (int n)
签入时设置。 更改后, bgc_thread
现在在执行开始时在新线程中设置,这似乎会引入竞争条件,即可能无法及时设置该字段以继续并发 GC。
啊,好找!
@PeterSolMS , @VSadov请你们中的一个人看看并进行修复吗?
只是想指出,这里完成的实际 GC 不再是 BGC——它只是将它视为我们未能创建 BGC 线程,因此我们只是在进行全阻塞 GC; 该事件具有误导性(它仍然表示背景),因此如果我们未能实际执行 BGC(未能创建 BGC 线程或由于任何其他原因),也应该修复该事件。
对于设置 bgc_thread 的竞争,我们实际上不需要在bgc_thread_stub
设置它,在此行之后的CreateSuspendableThread
args.Thread = SetupUnstartedThread(FALSE);
Thread 对象已经可用 - 此函数中的所有后续逻辑都不会更改已创建的 Thread。
最有用的评论
只是想指出,这里完成的实际 GC 不再是 BGC——它只是将它视为我们未能创建 BGC 线程,因此我们只是在进行全阻塞 GC; 该事件具有误导性(它仍然表示背景),因此如果我们未能实际执行 BGC(未能创建 BGC 线程或由于任何其他原因),也应该修复该事件。