About Java, parallel garbage collection and processor sets
Garbage Collection is still one of interesting topics in the Java world. There was and is a lot of development in this realm , lead from simple mechanisms over Parallel Garbage collection over Concurrent Mark Sweep and leads to G1. I don’t want to talk about the simple mechanisms, i don’t want to talk about the G1, i want to talk about the both in the middle, and i don’t want to talk about the garbage collection itself. I’m a operating system guy, thus i want to look at them at the “damned, even more processes with fscking long process names” perspective. On interesting question with those parallel and concurrent garbage collection mechanisms is: How many threads are running in parallel to do this job. There are an simple formula to do this computation. I’ve looked them up in the source code of JDK6u21.I found several different versions in blogs, thus i wanted some more authoritative.
Let’s look at first at the number of threads for the ParallelGC. When you have less than or exactly 8 CPUS the formula is simple.
When you have more than 8 CPUs, it’s getting a little more complex. (By doing so, they want to prevent you from ending up with 512 GC threads on a fully blown M9000 ;) )
The number of threads for the ConcurrentMarkSweep process is dependent on the number of the threads for the parallel GC.
Those math is not a problem in itself. The problem arises when you have more than one running java process on your system. Because each of them does the same math and it thinks it’s the only one on the system. One example. Let’s assume you have an 8 core system, let’s say you run 6 JDKs in it. Then you will have 48 ParallelGC threads and 12 ParallelCMS Threads alone. And that’s a little to much.
There are two solutions to prevent the system to have too much GC threads. The first one is to directly intervene into this calculation and simply setting both values by hand. You can do this via
-XX:ParallelCMSThreads=n. But i’m not a fan of such hard-coded things … out of simple reasons … people tend to forget them when they migrate them to different locations.
Another way is to leave the default mechanisms in action and using the single variable in the equation as an control instrument: The number of processors usable by Java. In Solaris you could use processor sets for this task. To get back to our 6 java processes on 8 procs. If you divide them into 6 processor sets with one proc each and leave the other 2 procs for housekeeping networking, interrupt and so on. each JDK will just start 1 ParallelGCThread and 1 CMS threads. Thus 6 ParallelGC Threads instead of 48 and 6 instead of 12 CMS threads. Okay, you could argue about the sense of ParallelGC/CMS here), but you should get the point.
Issues may look in the mirror more distant than they are.
That isn’t only a issues of the big boys with their 512 core systems. Think of the point that even a quad-socket Nehalem system with HT and hex-cores is 48-core system (the same for the 12-core quad socket Opteron-Systems) from the perspective of the os and thus from the perspective of Java.