Troublesome GC.collect() calls in third-party library
While profiling my app (C#, .NET 4), I noticed a third-party library I am using explicitly calls GC.Collect(). This is very annoying because it sometimes has a dramatic impact on my app performance, as some calls to this library end up in huge loops: time spent in GC.Collect account for more than 80% of the total execution time.
Of course, I reported this behaviour to the library maintainers (the lib is开发者_Go百科 not open-source), but while they are working on a new version I'd like to optimize my app. What can I do?
I tried to configure the GC by setting GCSettings.LatencyMode to GCLatencyMode.LowLatency (only during the execution of the library calls, of course), but to no avail. I'd rather avoid forking my process.
Any ideas?
There are two roads you can take, the first is patching it yourself, the second is informing the developer of the library about it (filing a bug report).
Patching it yourself is rather easy, get RedGates Reflector together with the Reflexil AddIn and patch the library. You can also get the DotNet IL Editor, which basically does the same thing, but is FLOSS.
The problem with the "patch it yourself" approach is that it has drawbacks:
- Future versions of the libraries will also need to be patched. So you better keep records of what you did.
- You do not understand the internals of the library, if there are 10 calls to
GC.Collect()
and only one of them is legitimate (I doubt it, but could be), you'll break the library by removing all of them. - You will most likely violate the license of the library, which can send you into legal hell. But it depends on how you use the library and in what software and how that final package is distributed.
The other thing you can do is file a bug with the original developers of the library. Make sure that you're not smug about it and instead provide helpful resources, like the MSDN article on the GC and a test application together with the results of the profiler which shows the problem.
Before trying to hack things to prevent the code from performing a GC, it may be useful to ask why it does. While well-written code should simply let the GC be invoked when .Net thinks it's necessary, it's certainly possible to write code which requires that the GC be run at certain times to ensure correctness. I can imagine three reasons the code might be calling the GC:
- GC calls were added for memory-profiling purposes, and inadvertently/inappropriately left it.
- The developer thought it seemed like a good idea, even though it provides no real benefit.
- Some type of managed resource was incorrectly abandoned; forcing a GC may allow such abandoned resource to be cleaned up in sufficiently-timely fashion to allow correct (albeit slow) program execution.
If the forced GC exists because of scenario 3, removing it may cause bad things to happen.
精彩评论