Java - Tuning GC for Java audio application
I've noticed that when playing audio in java, MarkSweepCompact stage in gc is too long and results in short periods of silence, which is unacceptable. So I need to use a low pause gc. I've tried Parallel and CMS, they seem to work better because I suppose the pause is shorter and they don't do full collection as often as the default one.
So far I've tested my program with the following options for ParallelGC:
and for ConcurrentMarkSweep:
-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing
I also tried G1GC, but it's still experimental in java 6. Options for both modes:
-Xms15m -Xmx40m -XX:+UnlockExperimentalVMOptions -XX:+CMSClassUnloadingEnabled -XX:+TieredCompilation -XX:+AggressiveOpts -XX:+UseAdaptiveSizePolicy -Dsun.java2d.noddraw=false -Dswing.aatext=true -XX:MaxPermSize=25m -XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=10
Which GC is better in this situation? Can any of these settings be optimized for best CPU performance and minimal memory usage as well?
EDIT To recognize the pause I record time to write audio data to the output line, usually it's between 92 to 120 ms (I'm writing 16384 bytes = ~92ms), ad when Full GC is run, it's 200+ ms:
65.424: [Full GC (System) [PSYoungGen: 872K->0K(2432K)] [PSOldGen: 12475K->12905K(16960K)] 13348K->12905K(19392K) [PSPermGen: 15051K->15051K(22272K)], 0.2145081 secs] [Times: user=0.20 sys=0.00, real=0.21 secs] Was writing 16384 bytes, time to write 263 ms
EDIT2 Allocation pattern for my app is the following: it loads bunch of objects at startup, then it starts playing and I guess most of the objects after that are allocated by the gui, because staring/pausing the audio doesn't change the GC graph much. This is what visualgc shows with parallel gc:
The graph starts at startup and I start playback. Labeled are
1) sound delay and full gc, I think it increased Old size:
101.646: [Full GC [PSYoungGen: 64K->0K(6848K)] [PSOldGen: 15792K->12773K(19328K)] 15856K->12773K(26176K) [PSPermGen: 15042K->14898K(23808K)], 0.2411479 secs] [Times: user=0.19 sys=0.00, real=0.24 secs]
2) I open the app window and pause playback. Nothing really changes, a bit later it increases eden size.
3) I open the windows and start playback again.
So I need to increase allocated Old Gen size? How do I do that? I'm running with -XX:NewRatio=10 and -XX:NewSize=10m
There are 4 suggested solutions here and each one has been listed below with a detailed description. The following topics have been covered briefly such as Performance, Java, Audio, Garbage Collection. These have been categorized in sections for a clear and precise explanation.