Is GC.Collect() blocking?
I'm running some benchmark tests over my code and I want to make sure a garbage collect doesn't occur during one of my benchmarks because it's cleaning up the mess of a prior test. I figure my best chance of this is to force a collect before starting a benchmark.
So I'm calling GC.Collect() before a benchmark starts but not sure if a collect continues to run in a separate thread, etc and returns imme开发者_如何学运维diately. If it does run on a BG thread I want to know how to call it synchronously or a at least wait til it's finished the collect.
As MSDN states - Use this method to try to reclaim all memory that is inaccessible.
Anyway, if it does starts Garbage collection you should wait to all finilizers to finish before start benchmarking.
GC.Collect();
GC.WaitForPendingFinalizers();
Since .NET Framework 4.5 you can specify whether the GC collection should be blocking:
GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized, blocking: true);
or
GC.Collect(GC.MaxGeneration, GCCollectionMode.Default, blocking: true);
GCCollectionMode.Default
currently defaults to GCCollectionMode.Forced
For more details, see:
MSDN: GC.Collect Method (Int32, GCCollectionMode, Boolean)
MSDN: Induced collections - guide
If you want to benchmark your code, it should be done over a course of many iterations and as an average. You are never guaranteed when GC is run in the first place.
You should just assume:
- GC runs some times, and not some others.
- Heavy stuff happens in some unrelated processes some times, and not some others.
- Something crazy happens every now and then.
And hence do several iterations of the tests you are doing, remove the highest and lowest (assume they were flukes either way) and average what's left. This will give you meaningful comparisons.
The way GC in .Net works is to stop all threads (at least for a part of full collection, which is what GC.Collect()
does). So you could say it is very synchronous, it's not blocking just one thread, but all of them. And calling GC.Collect()
will perform the collection and return only after it finished, so, GC.Collect()
is the way to run it synchronously.
There is one part related to GC that is run on a background thread – finalizers. If you want to make sure all finalizers are finished before you run your benchmark and that all finalized objects are actually collected, use:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
That being said, there is no way to make sure that the GC won't run. And I don't understand why do want to do that. If, for example, your code is creating lots of temporary objects, the GC should be part of your benchmark, for better or worse, you should not try to exclude it.
精彩评论