我们的多线程应用程序执行了一个冗长的计算循环。平均而言,完成一个完整的周期大约需要 29 秒。在此期间, GC 中的 .NET 性能计数器% time测量为 8.5%。它全部由 Gen 2 系列制成。
为了提高性能,我们为我们的大对象实现了一个池。我们实现了 100% 的重用率。整个周期现在平均只需 20 秒。“% time in GC”显示在 0.3...0.5% 之间。现在 GC 只进行 Gen 0 收集。
让我们假设,池化被有效地实现并且忽略了执行所需的额外时间。比我们获得了大约 33% 的性能提升。这与之前 8.5% 的 GC 值有何关系?
我有一些假设,希望能得到确认、调整和修正:
1)“GC中的时间”(如果我没看错的话)确实测量了2个时间跨度的关系:
- 2个GC周期之间的时间和
- 上次完整 GC 循环所用的时间,该值包含在第一个跨度中。
第二个时间跨度不包括的是为阻塞 GC 停止和重新启动工作线程的开销。但这怎么可能占总执行时间的 20%?
2)频繁阻塞GC线程可能会引入线程之间的争用?这只是一个想法。我无法通过 VS 并发分析器确认这一点。
3)与此相反,可以确认非池化应用程序的页面未命中数(性能计数器:内存 -> 页面错误/秒)显着高于具有低 GC 率的应用程序(每秒 25.000 次) (每秒 200 个)。我可以想象,这也会带来很大的进步。但是什么可以解释这种行为呢?是不是因为频繁的分配导致使用虚拟内存地址空间中更大的区域,因此更难保留到物理内存中?又如何衡量以确认是这里的原因呢?
顺便说一句:GCSettings.IsServerGC = false,.NET 4.0,64 位,在 Win7、4GB、Intel i5 上运行。(很抱歉这个大问题.. ;)