2

How do I drive the garbage collection activity to some significant level, say, 10% or more, preferrably without running into an out-of-memory condition?

I have been trying to build code that does this, but I'm not getting anywhere near 10%.

What approaches are there? I tried a pool of randomly-sized blocks which are being replaced in random order, with newly created randomly-sized-again blocks; this is giving me ca. 20% CPU and 0.6%GC in VisualVM, slightly varying with pool and block sizes.

toolforger
  • 754
  • 7
  • 22
  • Please reopen, the other question has just a single answer, which is not even fully accurate (1: a linked list should not make GC work more, 2: the answer demonstrates how to go into OutOfMemoryError, not about creating a sustained high GC rate). – toolforger Jun 26 '21 at 12:13
  • Also, that other question is specifically about generating OldGen objects, this question is about stressing the GC in general. – toolforger Jun 26 '21 at 12:17

4 Answers4

1

You might want to take a look here to get few ideas. Basically the technique used in above example is to create fragmentation of Java heap memory as objects are added and removed from the LinkedHashMap being used as a cache. Running on my local with 300m max memory to JVM (java -Xmx300m -jar gcstress.jar) I was able to generate 20% consistent CPU usage for garbage collection.

enter image description here

Shailendra
  • 8,874
  • 2
  • 28
  • 37
  • Hm... this is weird. A first look at your code made me believe that your explicit control of thread priorities would make the difference, but it didn't help my code. It seems that I'm doing the right thing but missed some detail, and I was asking the wrong question - I'll take your code and gradually transform it into what I'm doing, to figure out what trap I ran into. – toolforger Jun 20 '21 at 10:40
  • Fragmentation is not a problem for typical Java heaps. They coalesce / compact the free space. Whatever is causing this load ... it is unlikely to be fragmentation per se. – Stephen C Jun 20 '21 at 12:34
  • Weird. My machine seems to stick at 5% where yours is at 20%. Either we use different GCs (I'm using default GC on OpenJDK 11), or our machines have very different hardware characteristics. But maybe your -Xmx is closer to the spot where you keep GC active but don't run into OOM. – toolforger Dec 04 '21 at 21:19
1

You can do a humongous allocation (assuming G1GC with defaults):

public class Del {

    public static void main(String[] args) {
        for(int i=0;i<100_000;++i) {
            System.out.println(allocate());
        }
    }

    private static int allocate() {
        int [] x = ThreadLocalRandom.current().ints(1024 * 1024, 10, 10_000_000).toArray();
        return Arrays.hashCode(x);
    }

}

You can constrain the heap and also enable GC logs to see how bad is G1 trying to cope with the constant allocations:

java -Xmx100m -Xms100m "-Xlog:gc*=info" Del.java

Running this on my machine shows that the CPU is occupied, constantly, from that java process, because of constant GC activity.

Eugene
  • 117,005
  • 15
  • 201
  • 306
0

One way to cause the GC to spend a lot of time is to almost fill up the heap and then trigger repeated garbage collections by allocating and discarding1 lots of temporary objects.

A typical generational GC spends most of its time tracing and moving non-garbage objects from one space to another. When the heap is nearly full of non-garbage objects, and you trigger the GC repeatedly, it does a lot of work for very little gain (in terms of space reclaimed).

Another way (assuming that explicit GC has not been disabled) is to repeatedly call System.gc().


1 - That is, not keeping a reference to the object so that it is almost immediately unreachable.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • That's what I'm doing: a pool of `byte[]` objects, randomly replacing them with new `byte[]` objects. The best I could achive was GC activity of 3%. – toolforger Jun 20 '21 at 09:47
  • But did you do the first part? Fill up the heap with **reachable** objects so that it is permanently "almost full"? – Stephen C Jun 20 '21 at 09:48
-1

[ONLY for debugging] Reduce the -XX:NewSize JVM parameter to a smaller size to trigger GC. This is for older GCs.

You can call System.gc() in program. Read here: Why it is bad to call System.gc()

The Roy
  • 2,178
  • 1
  • 17
  • 33
  • Is there documentation for that parameter? I could find it via Google but the page looked outdated, and I have to document what to expect under what circumstances. – toolforger Jun 20 '21 at 09:42
  • -Xmn only applies to older GCs, and is not advised by mainline ones such as G1 – Sheinbergon Jun 20 '21 at 09:55