8

I'm doing an intro presentation on the .Net CLR GC and have all the various pieces, but I wanted an example specifically of how trying to force collection could be dangerous or harmful. I know you can force things into higher generations prematurely, but (from what I could tell) that would really only slow things down.

I'm trying to think of a situation where forcing GC could be truly damaging and I keep coming up w/ merely less efficient solutions.

Rikon
  • 2,688
  • 3
  • 22
  • 32
  • 2
    Loss of time is the only downside. – Dialecticus Jul 23 '12 at 19:57
  • By "forcing collection" I assume you mean by calling GC.Collect(). Why would you think that would be dangerous? Is there some documentation that I missed that says so? (I realize the likelihood is high, as I can't keep up these days.) – David Jul 23 '12 at 19:58
  • Tight timer with real-time requirements maybe? – leppie Jul 23 '12 at 19:58
  • 3
    Curious to know what would happen if you ran GC.Collect() in parallel. – Inisheer Jul 23 '12 at 20:02
  • @DavidStratton I do mean GC.Collect... And by dangerous, I'm asking if there's a way to put data into an unstable state or something – Rikon Jul 23 '12 at 20:08
  • @JTA that's exactly the kind of oddities that I couldn't think of but suspected were out there... – Rikon Jul 23 '12 at 20:09
  • 2
    @Dialecticus Also high memory usage, since objects will be promoted into longer-lived generations prematurely, causing them to resist collection longer. – Raymond Chen Jul 23 '12 at 20:11
  • 2
    @JTA [“Any public static members of this type are thread safe.”](http://msdn.microsoft.com/en-us/library/system.gc.aspx) I believe that's the case for all `public static` members in the whole framework. – svick Jul 23 '12 at 20:13
  • The behavior of `GC.AddMemoryPressure` is the best example of interfering with the GC causing weird behavior. See http://stackoverflow.com/questions/7331735/gc-is-forced-when-working-with-small-images-4k-pixel-data – CodesInChaos Jul 23 '12 at 20:30
  • @svick - Great, thanks for the link/info. I figured MS was smarter than me... but you never know. – Inisheer Jul 23 '12 at 20:33

2 Answers2

4

Here's an interesting demonstration. Note you should run this demo compiled in release mode or it may not work as advertised.

Version 1:

private void Button_Click(object sender, EventArgs e)
{
    Timer timer = new Timer(Print, null, 0, 1000);
}

private void Print(Object o)
{
    if (textBox1.InvokeRequired)
    {
        Action<object> action = Print;
        textBox1.Invoke(action, o);
        return;
    }

    textBox1.Text = DateTime.Now.ToString();
}

Version 1 will happily print the date and time to the text box once a second.

Version 2:

private void Button_Click(object sender, EventArgs e)
{
    Timer timer = new Timer(Print, null, 0, 1000);
}

private void Print(Object o)
{
    if (textBox1.InvokeRequired)
    {
        Action<object> action = Print;
        textBox1.Invoke(action, o);
        return;
    }

    textBox1.Text = DateTime.Now.ToString();

    GC.Collect(); // force a garbage collection
}

Now in Version 2, the date and time will only be printed once because, after the declaration, there are no more references to the timer object, and so the timer object gets collected.

That's a fairly contrived example but may make for a good demonstration.

I must credit Jeffery Richter for this one - it's in his excellent book CLR via C#.

James
  • 2,823
  • 22
  • 17
  • I believe this behavior would be more unexpected if you just called `new Timer(...` and didn't save the return value. – Dour High Arch Jul 23 '12 at 20:36
  • 2
    But in this case, `GC.Collect()` isn't bad, it's actually good, because it helped you discover a bug in the application. Without `GC.Collect()`, it would mysteriously stop working some time in the future. – svick Jul 23 '12 at 23:29
  • @svick - good point. perhaps it's just a better lesson on scoping. in any event, it is interesting and it gets one thinking about the GC. – James Jul 23 '12 at 23:59
1

What about the following, bad idea? "Let's force a GC after every HTTP request in ASP.NET in order to clean up request state which will surely be orphaned!"

That's a bad idea because concurrent HTTP request would interfere with each other. This would introduce lots of latency spikes and destroy performance. All that starting from an innocent "optimization".

That's about the worst I can think of.

usr
  • 168,620
  • 35
  • 240
  • 369