C# 第三方库中的GC.collect()调用很麻烦
在分析我的应用程序(C#,.NET4)时,我注意到我正在使用的第三方库显式调用GC.Collect()。这非常烦人,因为它有时会对我的应用程序性能产生巨大的影响,因为对这个库的一些调用最终会以巨大的循环结束:花费在GC中的时间。Collect占总执行时间的80%以上 当然,我向库维护人员报告了这种行为(库不是开源的),但当他们正在开发新版本时,我想优化我的应用程序。我能做什么 我试图通过将GCSettings.LatencyMode设置为GCLatencyMode.LowLatency(当然,仅在库调用执行期间)来配置GC,但没有效果。我宁愿避免分岔C# 第三方库中的GC.collect()调用很麻烦,c#,.net,performance,garbage-collection,profiling,C#,.net,Performance,Garbage Collection,Profiling,在分析我的应用程序(C#,.NET4)时,我注意到我正在使用的第三方库显式调用GC.Collect()。这非常烦人,因为它有时会对我的应用程序性能产生巨大的影响,因为对这个库的一些调用最终会以巨大的循环结束:花费在GC中的时间。Collect占总执行时间的80%以上 当然,我向库维护人员报告了这种行为(库不是开源的),但当他们正在开发新版本时,我想优化我的应用程序。我能做什么 我试图通过将GCSettings.LatencyMode设置为GCLatencyMode.LowLatency(当然,仅
有什么想法吗?有两条路可以走,第一条是自己修补,第二条是通知库的开发人员(提交错误报告) 自己修补是相当容易的,请与一起修补库。你也可以得到牙线,它基本上做同样的事情,但是是牙线 “自己修补”方法的问题在于它有缺点:
- 这些库的未来版本也需要修补。所以你最好把你所做的记录下来
- 您不了解库的内部结构,如果有10个对
的调用,并且其中只有一个是合法的(我对此表示怀疑,但可能是合法的),您将通过删除所有调用来破坏库GC.Collect()
- 你很可能会违反图书馆的许可证,这会把你送进法律地狱。但这取决于您如何使用库,在什么软件中,以及最终包是如何分发的
您可以做的另一件事是向库的原始开发人员提交一个bug。请确保您没有自鸣得意,而是提供有用的资源,例如关于GC的MSDN文章和测试应用程序,以及显示问题的探查器的结果。在尝试进行黑客攻击以防止代码执行GC之前,询问其原因可能很有用。虽然编写良好的代码应该只在.Net认为有必要时调用GC,但当然也可以编写需要在特定时间运行GC以确保正确性的代码。我可以想象代码调用GC的三个原因:
如果由于场景3而存在强制GC,删除它可能会导致不好的事情发生。我很确定答案是“没有”。毕竟,GC.Collect是执行垃圾收集的显式请求;我想不出一种方法来“覆盖”请求,或者显著降低它的影响。我很想知道最初的开发人员认为他们正在做什么,将GC.Collect调用放入他们的库中!当你与他们联系时,不要表现得太好。@Rob Levin:他们可能认为
在这里执行垃圾收集以释放资源是个好主意。当我开始使用.NET时,我也有这样的想法……不用说,在这个伟大的想法产生两个小时后,我通过阅读为什么我的应用程序的性能突然那么差,了解了为什么我不应该弄乱框架的GC。呵呵。。我希望这个工具以前存在。我以前想使用类似的方法将用于身份验证的webrequest代理破解到已签名的程序集中,但由于签名而被难倒。您可以使用Reflecil在本地计算机上禁用特定程序集的程序集签名验证。或者,您可以删除强名称,然后修复引用集合。实际上,我已经看到了一个场景,该场景将出现在您的3中。异步套接字库将“忘记”处理底层本机套接字,而这只会在终结器队列中释放。但是,套接字尝试正常关闭,因此每个释放的套接字最多会阻塞终结器队列四分钟。在这段时间里,端口被阻塞(无法重用)。AGC.Collect();GC.WaitForPendingFinalizers();GC.Collect()
似乎神奇地解决了这个问题,尽管根本的问题当然是被遗忘的socket.Close()代码>调用。@Luaan:我希望.NET规范编写得更好,以便更容易避免IDisposable
泄漏[例如,允许类指定如果其构造函数或任何派生类的构造函数抛出异常,Dispose
应被调用],以及处理可能需要一段时间且可能无法成功的清理方法[例如,允许Finalize
方法指示“我还不能完成清理,但可能在XX毫秒内完成”;然后,终结器线程可以在返回到尚未能够运行的方法之前处理其他终结器]@Luaan:即使有这样的功能,也可能需要保留正在清理的套接字的ConcurrentDictionary
,以便在正在清理的套接字上进行打开
尝试的等待时间要比在仅忙且不期望可用的套接字上进行打开尝试的等待时间长。