Not game related, but it might interest you just the same.
My company makes video encoding stuff. We have our own capture cards and a fancy app that does video encoding and braocasting using various codecs. The UI is written in Java. It runs on Windows and the same UI code provides a remote interface to our encoders on Linux and Mac. My test were done on 1.5.0_01, since 1.5.0_03 or _04 will crash hard in jvm.dll if you let it run for 30 hours or so.
Recently while testing we found that the hardware was dropping frames of video because the software wasn’t emptying the hardware’s FIFO fast enough. This happened when the Concurrent Mark Sweep collector did a full sweep. There is a driver thread that runs at the highest windows priority (31) that is responsible for emptying the hardware FIFO. That thread is running in the System process, quite separate from the UI application.
After much experimenting I found that the ‘sweep’ phase of the CMS collector would run for a bit over 200 ms. During that time there was a lot of thread context switching and it managed to starve the high priority driver thread for long enough (100ms) that the hardware FIFO overflowed.
Incidentally, my code during a test does nothing but query some stats from another process and display them on a Swing UI. It has one indeterminant progress bar and several JLables that update once a second. As far as I know I generate no new objects that should live more than one second during this process. Most of the time the app is idle. A polling thread wakes up every second and collects some stats via JNI.
I switched to the openGL pipeline and the problem went away. Checking the GC activity showed that with the default graphics pipeline on windows or with nodraw=true the CMS sweep was as I said 200ms+. Simply switching to the OpenGL pipeline and changing nothing else in the application the time taken for the CMS sweep phase was reduced by a factor of 10, though it happened a bit more frequently. Lowering the max heap size (to 20MB) also made the problem go away, by increasing the freqency and shortening the duration of the CMS sweep phase.
Because the OpenGL pipeline was not stable on all the hardware we needed to support, we searched for another solution and found it with the -XX:+CMSIncrementalMode option (used in addition to the -XX:+UseConcMarkSweepGC that we were already using).
What I find most disturbing about this is that the GC thread could possibly starve a thread in the system process that is set to the highest possible priority. I have many questions:
What priority does the GC thread run at?
What about the finalizer thread?
Why do any objects accumulate in the tenured generation at all? (Every object I make is small and lives for at most one second. The young generation should easily deal with them.)
My thread does little more than while(true) { lable.setText("frame "+x); Thread.sleep(1000); }, though with a few more JLabels, a hidden JTable, and a progress bar animating.
Next I have to figure out why jvm.dll always crashes at the same spot after running for a couple days… though for now 1.5.0_01 will save me from that.