【发布时间】:2014-02-17 12:20:20
【问题描述】:
我正在使用 VS 2012 中的采样分析应用程序(尽管分析器并不重要)。我对性能瓶颈所在有一个很好的引导,但是,我受到以下事实的阻碍,即正在进行大量内存分配,并且垃圾收集器似乎严重扭曲了我的分析(我可以在一定程度上看到 GC 效果在 CLR Profiler 和并发可视化工具中)。
有没有办法以某种方式摆脱 GC 运行时采集的样本?我可以使用其中任何一个:
- 在 GC 运行时忽略收集的样本(按函数指针过滤?)
- GCing 花费的时间和实际工作花费的时间分开
- 增加 GC 限制以有效地“关闭”以进行分析
- 实际关闭GC
问题是我几乎不知道我需要优化什么。通过减少分配等来优化 GC 的尝试对没有附加调试器的发布版本的实际影响非常低,所以我真的想知道有多少分析结果是由于禁用优化等,以及有多少代码可以有待改进(我们的大部分项目都使用了相关代码,因此即使性能提高 10% 也会产生巨大影响)。
【问题讨论】:
-
您无法将其关闭,也无法希望它消失。在我看来,您发现了应该首先解决的真正的瓶颈。你产生了太多的垃圾。也许您可以重复使用缓冲区。也许这太不切实际了,而且它已经达到了预期的效果。
-
@HansPassant 问题是我不知道代码是否真的只是 CPU 密集型的,因为获得最多样本的特定函数也在进行大量分配(以及其余的由于以前的优化,应用程序几乎没有任何作用),因此导致该代码中的 GC,即使这不一定是它们的原因。我无法将 GC 的“真实”工作与“偷走”的 CPU 隔离开来——即。问题是 - 优化哪个:分配还是计算?如何使用分析数据将两者分开?
-
好吧,只是不要假设 GC 不是真正的工作。也就是说,分配内存不是免费的,而且你的代码在用户机器上也会被它减慢。所以问题不在于你的代码太密集,问题在于它使用了太多的内存。这是完全正常的,相信分析器告诉你的。并专注于通过更有效地使用内存来改进它。
-
@HansPassant 好吧,这正是我的问题——我不知道是不是 GC 给我带来了麻烦。我的代码绝对是 CPU 密集型的,而且肯定会造成很大的内存压力。但我不知道如何使用分析数据来确定两者中哪一个更重要。在实践中,我发现虽然我的内存优化在 CLR 分析器中创造了奇迹(分配的字节从 2.5 GiB 下降到 ~100 MiB),但在发布版本中,它们对性能的影响非常低。似乎进一步优化内存使用也将收效甚微。
-
我会说它比这更复杂。 GC 可以做很多工作而不影响应用程序的性能。 GC 的最大影响来自于它有时必须挂起托管线程以安全地在堆上移动对象。发生这种情况时,CLR 会输出 ETW 事件。将这些事件与您自己的事件相关联可以让您很好地了解 GC 如何影响您的应用程序的性能。
标签: .net visual-studio-2012 garbage-collection profiling