2

I remembered someone telling me one good one. But i cannot remember it. I spent the last 20mins with google trying to learn more.

What are examples of bad/not great code that causes a performance hit due to garbage collection ?

10 Answers10

2

What are examples of bad/not great code that causes a performance hit due to garbage collection ?

The following will be inefficient when using a generational garbage collector:

  1. Mutating references in the heap because write barriers are significantly more expensive than pointer writes. Consider replacing heap allocation and references with an array of value types and an integer index into the array, respectively.

  2. Creating long-lived temporaries. When they survive the nursery generation they must be marked, copied and all pointers to them updated. If it is possible to coalesce updates in order to reuse of an old version of a collection, do so.

  3. Complicated heap topologies. Again, consider replacing many references with indices.

  4. Deep thread stacks. Try to keep stacks shallow to make it easier for the GC to collate the global roots.

However, I would not call these "bad" because there is nothing objectively wrong with them. They are only inefficient when used with this kind of garbage collector. With manual memory management, none of the issues arise (although many are replaced with equivalent issues, e.g. performance of malloc vs pool allocators). With other kinds of GC some of these issues disappear, e.g. some GCs don't have a write barrier, mark-region GCs should handle long-lived temporaries better, not all VMs need thread stacks.

J D
  • 48,105
  • 13
  • 171
  • 274
2

from an old sun tech tip -- sometimes it helps to explicitly nullify references in order to make them eligible for garbage collection earlier:

public class Stack {
  private static final int MAXLEN = 10;
  private Object stk[] = new Object[MAXLEN];
  private int stkp = -1;

  public void push(Object p) {stk[++stkp] = p;}

  public Object pop() {return stk[stkp--];}
}

rewriting the pop method in this way helps ensure that garbage collection gets done in a timely fashion:

public Object pop() {
  Object p = stk[stkp];
  stk[stkp--] = null;
  return p;
}
Rahel Lüthy
  • 6,837
  • 3
  • 36
  • 51
  • I believe local variables are only GC'd when the method returns. – Joel Oct 04 '11 at 07:40
  • 2
    @Joel Heap allocated blocks of memory get GC'd, not variables, and they can be collected at any point after they become unreachable, which has nothing to do with variable scopes. – J D Jun 19 '12 at 13:44
1

When you have some loop involving the creation of new object's instances: if the number of cycles is very high you procuce a lot of trash causing the Garbage Collector to run more frequently and so decreasing performance.

Stefano Driussi
  • 2,241
  • 1
  • 14
  • 19
  • 2
    This is actually what generational garbage collectors are specifically optimized to be good at. – J D Jun 19 '12 at 13:46
0

I have encountered a nice example while doing some parallel cell based simulation in Python. Cells are initialized and sent to worker processes after pickling for running. If you have too many cells at any one time the master node runs out of ram. The trick is to make a limited number of cells pack them and send them off to cluster nodes before making some more, remember to set the objects already sent off to "None". This allows you to perform large simulations using the total RAM of the cluster in addition to the computing power.

The application here was cell based fire simulation, only the cells actively burning were kept as objects at any one time.

whatnick
  • 5,400
  • 3
  • 19
  • 35
0

One example would be object references that are kept in member variables oder static variables. Here is an example:

class Something {
  static HugeInstance instance = new HugeInstance();
}

The problem is the garbage collector has no way of knowing, when this instance is not needed anymore. So its usually better to keep things in local variables and have small functions.

Lemmy
  • 3,177
  • 3
  • 17
  • 16
  • Actually if your instance is 85000 bytes it will be allocated on the LOH(Large Object Heap) which is rarely scanned for roots and doesn't incur much overhead... – Matt Davison Jan 27 '09 at 13:27
  • ok but it still needs RAM that is therefore not available to other objects. my point is just that you should always define your variables at the smallest possible scope. beside being better style it just helps the GC better understand the lifecycles of your objects. – Lemmy Jan 27 '09 at 13:32
0
String foo = new String("a" + "b" + "c");

I understand Java is better about this now, but in the early days that would involve the creation and destruction of 3 or 4 string objects.

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
0

I can give you an example that will work with the .Net CLR GC:

If you override a finalize method from a class and do not call the super class Finalize method such as



protected override void Finalize(){
    Console.WriteLine("Im done");
    //base.Finalize(); => you should call him!!!!!
}

When you resurrect an object by accident


protected override void Finalize(){
    Application.ObjJolder = this;
}

class Application{
    static public object ObjHolder;
}

When you use an object that uses Finalize it takes two GC collections to get rid of the data, and in any of the above codes you won't delete it.

mandel
  • 2,921
  • 3
  • 23
  • 27
0
  • frequent memory allocations
  • lack of memory reusing (when dealing with large memory chunks)
  • keeping objects longer than needed (keeping references on obsolete objects)
aku
  • 122,288
  • 32
  • 173
  • 203
0

In most modern collectors, any use of finalization will slow the collector down. And not just for the objects that have finalizers.

Darron
  • 21,309
  • 5
  • 49
  • 53
0

Your custom service does not have a load limiter on it, so:

  • A lot requests come in for some reason at the same time (everyone logs on in the morning say)
  • The service takes longer to process each requests as it now has 100s of threads (1 per request)
  • Yet more part processed requests builds up due to the longer processing time.
  • Each part processed request has created lots of objects that live until the end of processing that request.
  • The garbage collector spends lots of time trying to free memory it, however it can’t due to the above.
  • Yet more part processed requests builds up due to the longer processing time…. (including time in GC)
Ian Ringrose
  • 51,220
  • 55
  • 213
  • 317