Is Java freezing your system? Tune the garbage collector!
Posted on Tue 26 March 2013 in computing
I regularly open huge images and tables (>1 GB) in interactive Java-based
(astronomy) software such as Aladin and TopCat. Because of the
way memory allocation works in Java, the area where objects reside in
memory (called the heap) needs to be reserved up front using Java's
-Xmx
switch. Hence I tend to run memory-intensive applications
using:
java -Xmx4000m
If you don't use this flag you will get an OutOfMemoryError
exception as soon as your application exceeds the default heap size,
which is typically set at only a few hundred megabytes.
However, I frequently found myself faced with a horrible performance experience when using a large heap. Java applications would freeze my entire (64-bit) Linux system for anywhere between 2 and 60 seconds. This happened regardless of the JVM used (I tried Oracle Java 1.7, Sun Java 1.6, GCJ 1.5). I verified that my system had plenty of memory available and was not swapping, hence a lack of memory was not to blame. A profiler revealed that these freezes were instead caused by an insane number of interrupts which ate 100% of all CPU cores in so-called "system" cycles.
The cause of these system freezes is Java's garbage collection mechanism; a built-in automated memory management system which reclaims memory occupied by objects that are no longer in use. Whilst this feature makes programming in Java a bit easier than, say, C++; it comes with the disadvantage that garbage collection in a large heap can introduce a considerable overhead. Some collection algorithms deal less effectively with large heaps than others, and unfortunately in my case, Java appeared to be using a collection strategy which paused the application during the whole duration of each garbage collection run, hence resulting in frequent freezing.
The trick to avoid these freezes is to tell Java to use a collection
strategy which runs concurrently to the application, hence avoiding
lengthy interruptions of the entire process. This can be achieved using
the -XX:+UseConcMarkSweepGC
flag, i.e.:
java -Xmx4000m -XX:+UseConcMarkSweepGC
There are in fact many more tuning parameters which can influence the
behaviour of the garbage collection, but UseConcMarkSweepGC
looks like
the first obvious thing to try if you are experiencing annoying freezes
in memory-intensive Java applications.