views:

878

answers:

7
+6  Q: 

GC.Collect()

Ok, I've read a couple of topics about it, but here it goes. Let's imagine I have an application where basically every now and then I will click on a button, a lot of things will happen for a couple of minutes, and then it'll stay idle possible for another hour, or maybe just 1 minute. Wouldn't just after that whole ended a good situation to call GC.Collect? I mean, I do know that just at that moment I will not being using my application, and GC cannot guess it.

+5  A: 

There's almost never a good reason to call GC.Collect().

In your case, there is absolutely no reason to call it. If you're idle for an hour, the GC will do its collections.

Randolpho
Yes, but it might be in the next minute. But just when I end my processing I do know that in that moment there will not be performance hit if I take a couple of seconds to do a GC.Collect().
devoured elysium
+1. calling GC.Collect() can actually promote an object's lifetime
Mitch Wheat
What do you mean with promoting an object's lifetime?
devoured elysium
When you call GC.Collect(), any objects that do not get collected get promoted so that they live longer elsewhere. Have a google for "generational garbage collection". Much as there may not be a perf hit for your app now, it may affect it later.
Matthew Steeples
Ah yes, I've read about it too. I wasn't taking that into consideration and that is, indeed, a good point.
devoured elysium
Well, now that I think of it, that wouldn't be that big of a problem, as it'd happen with a non-forced GC, too. What would happen is that probably I'd have more objects in generation1 and 2 in the long run, but I'd be sure to have always my generation0 space empty. That doesn't seem to be essentialy a bad thing to me.
devoured elysium
+15  A: 

It's almost always a premature optimization to worry about calling GC.Collect before you've prototyped or built the application and tested its performance. The GC is usually very good at collecting memory at the appropriate times. It will certainly run a collection while your application is idle, especially if there is memory pressure in the system.

It is much more important that you follow good generational GC allocation practices (small objects, short usage, etc.) and you will likely get the performance characteristics you are wanting. If you still don't have the performance you need, after profiling and good design you might think about GC.Collect as a solution.

Steven Lyons
Ok, that seems a more reasonable answer than the whole "no gc collections" i see popup everywhere.
devoured elysium
+1. Good explanation of *why* GC.Collect() is almost always unnecessary.
Randolpho
Very inclusive but concise
Guvante
+1  A: 

To know when to call GC.Collect(), you'd need to know details of the specific collector involved with the runtime along with detailed information about a weak point that you can solve with the collection.

In other words, if you really know when you need to call GC.Collect(), and it's not something you'd done poorly in other code, then you probably work for CLR Internals and can just fix the problem.

280Z28
My point is mainly this: there is nothing wrong that can happen if we GC.Collect(), right? If there's nothing wrong, then there's nothing to lose if we do it now that we know that at least for a moments our process will be idle, instead of having it done in some random moment. Or is anything here that I'm missing? Thanks
devoured elysium
Yes, calling GC.Collect() can have a devastating impact on the performance of your program. Or it could do nothing. The important thing to remember is: unlike the early days of Java, modern GCs are **very** good at their job and are *almost never* the culprit in application performance problems. In fact, the .NET and Java GCs are faster than many C/C++ allocator implementations.
280Z28
How can it have a devastating impact on the performance of my program? I'd say it'd have a devastating impact on the performance of my program if by chance it'd happen just while my process was running, not when I know it will be idle.
devoured elysium
It depends entirely on the implementation of `GC.Collect()` and underlying technologies. For example, a managed system might use a cross-process common allocator, where a `GC.Collect()` call freezes all applications instead of just one. There might, somewhere, somehow, be a place to call `GC.Collect()`, but if you know that place then you probably don't need to ask us any questions about it. :)
280Z28
+2  A: 

I'm hoping you're aware that calling GC.Collect doesn't cause more (or less) objects to be collected.

If you're trying to optimize for time, do you know the time GC takes to collect objects in your application? On desktop operating systems (XP, Vista etc..), the CLR uses a concurrent GC, and it can run without suspending all threads in the application for the duration of the collection.

Explicitly calling GC.Collect is not recommended because

  1. It throws the CLR GC Tuning algorithm out of gear. The tuner determines when to trigger a GC automatically, and forcing a manual GC messes with its calculations.

  2. By forcing a collection manually, you can end up promoting objects up a generation - objects which might have been collected in the next GC ( if they were "orphaned" before the GC decided to kick in).

You might find it interesting that .NET 4.0, a GC notification mechanism has been introduced for these kinds of scenarios.

Senthil Kumar
Thanks for the reply. I am not sure that I got the following point:"do you know the time GC takes to collect objects in your application? On desktop operating systems (XP, Vista etc..), the CLR uses a concurrent GC, and it can run without suspending all threads in the application for the duration of the collection.". From what I've read, seems like a GC collection is pretty fast(shouldn't take more than the time of a page fault for a generation 0 one).About your point 2), well that doesn't seem that good of an argument. The same applies to when you do a regular GC.
devoured elysium
If the GC collection is pretty fast, why bother calling it manually to save time?As for the second point, sure, the same thing happens when a regular GC occurs, but then the GC decides when to run, which again is determined by the GC tuning algorithm. It might figure out that there is a pattern in the way your application is allocating objects, and use that knowledge to trigger GCs at the best possible time w.r.t memory - in this case, a little later. That will collect more objects and promote fewer ones.
Senthil Kumar
It only gives me the impression people assume GC will now better than us programmers of how our program works. I may now that my process ocurrs every time my computer is idle 2 minutes, I find it hard to believe the GC will now the same thing. The whole argument of knowing when it's the best time to GC versus a manual GC doesn't seem to solid, just that.
devoured elysium
edit: know* in some places.
devoured elysium
Well, if you create every single object in the heap, and you can calculate all possible permutations of control in your code, then yeah, you'd know better than the collector.Even then, the GC might take into account things like available physical memory - it might decide to postpone it if there is heavy paging going on, for example. Those are things that are outside your control.Code is static, and except in very special cases, I'd think it'd be very hard to predict in advance the runtime conditions prevailing at the time of GC.Collect.
Senthil Kumar
A: 

Normally the GC is only called if you attempt to allocate new memory. If you don't run out of memory, you obtain 0% performance improvement from calling the GC. You have to have a pretty insanely resource intensive application to even come close to the limits of RAM on todays computers.

If you program has lots of external resources(like files or COM/DCOM references), you potentially would want to call the GC.

If calling the GC will give you peace of mind, then go ahead. It likely won't help, but it certainly wouldn't hurt.

William Crim
A: 

Yea as mentioned in other posts GC know when to start collection better than you, the factor that no buttons are clicked in your application doesn't mean that it is the time to start cleaning, GC is doing some kind of lockings when moving the objects, so this may cause low performance if you will abuse GC.Collect

ArsenMkrt
+6  A: 

I can see that several people have gone extreme about not recommending to call GC.Collect.

GC.Collect is there for a reason, here are my recommendation of when and why to call GC.Collect.

  1. In General, don't worry about calling it, GC tunes itself very well and will do the right thing.

  2. Sometimes, you end up in situation where you know for sure that this is the right time to call it, the situation you described above is exactly the right time to call it, in fact Asp.Net calls GC.Collect at certain points that are similar to what you described.

  3. The GC is smart about calling GC.Collect, if you called GC.Collect, the GC can override your decision and still doesn't collect ( you have to set a flag when you call GC.Collect to choose this behavior), this is the recommended way of calling GC.Collect, since you are still letting the GC decides if it is a good time to collect.

  4. Don't take my recommendation is a general statement for calling GC.Collect, you should always avoid calling it, unless you REALLY sure you need to call it, situation like the one you described is exactly why GC.Collect is there.

  5. The benefit you will get from calling it is freeing the garbage quickly, generally you will care about this situation if

    1. You are in low memory situation and want to be eager about collection, if you are in low memory situation, the GC will be aggressive anyway and will kick in automatically if the memory pressure is high on the machine
    2. If you want to avoid getting in low memory situation and you want to collect eagerly.

Hope this helps.
Thanks

mfawzymkh
Ah, finally....
devoured elysium
:) as i mentioned, don't take my recommendation as the general rule, it it the exceptional case; that just happened to match your case:)
mfawzymkh