2

I'm running a scheduling algorithm with a garbage collection snippet that looks like this:

    //garbage collection
    if (state.children.isEmpty()) {//if this is a leaf node (no children)
        state.parent.children.remove(state);
        System.gc();
    }

At first, the algorithm runs smoothly with no pauses; but after a while as the tree starts getting bigger, there's some sort of pause at each gc.

So I thought, maybe if a called gc less frequent? And modified my code to this:

    //garbage collection
    if (state.children.isEmpty()) {//if this is a leaf node (no children)
        state.parent.children.remove(state);
        if(index % 10000)
            System.gc();
    }

But this doesn't seem to actually do any cleanup, my program would throw an outOfMemory exception anyways.

How should I implement my garbage collector correctly so as not to be called too many times?

Some Noob Student
  • 14,186
  • 13
  • 65
  • 103
  • 4
    I would remove the System.gc() call completely, you are really not helping yourself by asking the jvm to run a full gc in a loop. How have you concluded that you need it? It is not like it is something you have to do instead of delete/free. Read this one: http://stackoverflow.com/questions/4784987/calling-system-gc-explicitly – Fredrik Jun 18 '11 at 07:42
  • But if I remove the gc, my program would definitely throw an outOfMemory exception. So I think the gc is required. – Some Noob Student Jun 18 '11 at 07:45
  • 2
    @Sheldon the OutOfMemoryError is thrown after the gc fails to free memory. Either your program needs more memory than is available or you hold references to unused objects. – josefx Jun 18 '11 at 07:51
  • 1
    @Sheldon Guess what happens before you get an out of memory exception? The GC will force a collection to make sure there is no memory it can allocate. Either you also removed something else in the process or you are having some other strange issue (like a config which doesn't match your needs). I think it would help you more to take a heap dump, look at it with MAT and see what is in there and also look at your jvm config. – Fredrik Jun 18 '11 at 07:52
  • 1
    You have a memory leak somewhere, by growing your data uncontrollably in your program. No amount of System.gc() calls will help that. You should split up the work and cache your data to file(s) and remove objects accordingly. If you really need more memory you should run your java app with larger heap memory set: http://www.caucho.com/resin-3.0/performance/jvm-tuning.xtp – Spoike Jun 18 '11 at 07:54
  • So this means that something is definitely wrong with my code which is causing memory leaks? – Some Noob Student Jun 18 '11 at 08:09
  • 1
    if your software relies on the gc call, then it is probably badly designed – clamp Jun 18 '11 at 08:29

2 Answers2

3

You shouldn't need to call the garbage collector explicitly at all. It's very occasionally appropriate, but I would normally be pretty suspicious if you find you need it.

Have you tried running with detailed GC logging turned on? It can be awkward to understand at first, but it should show you what's going on. I wouldn't be surprised to find that actually you've got a leak somewhere, and it's just that by GC-ing on every iteration, you've slowed your program down enough so that you just haven't reached the point at which it bites.

How much memory have you allocated for the VM? Tweaking the memory settings (and indeed the GC settings) can have a big impact on some workloads.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • So what you're saying is, if my program is written correctly which causes no memory leaks, it should run smoothly without the need to call gc? – Some Noob Student Jun 18 '11 at 08:06
  • 1
    @Sheldon: Yes. There are a *very few* situations where calling `System.gc` at exactly the right time can improve performance, and I've *very rarely* seen situations where the GC doesn't run in time on its own - but these are extremely rare... you should suspect your own code of being faulty before the GC. – Jon Skeet Jun 18 '11 at 08:20
2

The pause is probably garbage collection happening. As Frederik mentions, are you sure you have to invoke the GC manually? Generally you shouldn't need to. If you're concerned about your memory usage, feel free to prune your tree more often, but let the GC handle when to run, and don't invoke it manually.

You mentioned that your second snippet results in OutOfMemoryExceptions though, so maybe you have some other problems going on, you might want to show some more code.

kabuko
  • 36,028
  • 10
  • 80
  • 93