麻烦的GC.collect()调用第三方库

时间:2011-03-14 15:20:54

标签: c# .net performance garbage-collection profiling

在分析我的应用程序(C#,.NET 4)时,我注意到我使用的第三方库显式调用GC.Collect()。这非常令人讨厌,因为它有时会对我的应用程序性能产生巨大影响,因为一些对此库的调用最终会产生巨大的循环:在GC.Collect中花费的时间占总执行时间的80%以上。

当然,我向库维护者报告了这种行为(lib不是开源的),但是当他们正在开发新版本时,我想优化我的应用程序。我该怎么办?

我尝试通过将GCSettings.LatencyMode设置为GCLatencyMode.LowLatency来配置GC(当然,仅在执行库调用期间),但无济于事。我宁愿避免分支我的过程。

有什么想法吗?

2 个答案:

答案 0 :(得分:7)

您可以选择两条道路,第一条是自己修补,第二条是通知图书馆的开发者(提交错误报告)。

自己修补相当容易,与RedGates Reflector一起获取Reflexil AddIn并修补库。你也可以得到DotNet IL Editor,它基本上做同样的事情,但是是FLOSS。

“自己修补”方法的问题在于它有缺点:

  • 还需要修补库的未来版本。所以你最好记录下你做了什么。
  • 你不理解图书馆的内部,如果有10个电话GC.Collect()并且只有一个是合法的(我怀疑它,但可能是),你将通过删除全部来破坏图书馆他们。
  • 您很可能会违反图书馆的许可,这可能会让您陷入法律地狱。但这取决于您如何使用库以及使用什么软件以及最终包的分发方式。

您可以做的另一件事是向库的原始开发人员提交错误。确保您不会对此感到沾沾自喜,而是提供有用的资源,例如GC上的MSDN文章和测试应用程序以及显示问题的分析器的结果。

答案 1 :(得分:3)

在尝试入侵以阻止代码执行GC之前,先问一下它为什么会这样做。虽然编写良好的代码应该只是在.Net认为有必要时调用GC,但编写代码时肯定有可能需要在特定时间运行GC以确保正确性。我可以想象代码可能会调用GC的三个原因:

  1. 添加了GC调用以进行内存分析,并且无意中/不恰当地将其留下。
  2. 开发人员认为这似乎是一个好主意,尽管它没有提供真正的好处。
  3. 某些类型的托管资源被错误地放弃了;强制GC可以允许以足够及时的方式清理这种被放弃的资源,以允许正确(尽管很慢)的程序执行。

如果由于方案3而存在强制GC,则删除它可能会导致不良事件发生。