software - Java Sound dramatically slower after JVM 8 update



oracle java subscription (2)

My Application loads a bunch of audio clips at startup. It uses java.applet.Applet.newAudioClip(URL audioFileURL) to load the files, which are in the same folder. I could see that this function is basically a wrapper to get JavaSoundAudioClip objects

Until yesterday, I compiled the JAR with JDK 7 and launched it with JRE version 7 update 45. Then I updated to version 8 update 31.
Now, the loading of each audio takes ten times longer than before (was 0.2 seconds each, now it is between 2 and 3 seconds)
The same behaviour happened on different hardware configurations. OS is 64bit Windows 7, both Java 7 and 8 runtime environments are 32bit.

Digging deeper in debugging, I found that the methods that slowed down the most are AudioSystem.getAudioInputStream , AudioSystem.isLineSupported , AudioSystem.getLine

Audio format shouldn't be involved: I tried both OGG and WAV with the same results.

The settings for both JVMs are the same

EDIT: even I couldn't reproduce the problem in a small program made ad-hoc. Java 8 is slower indeed, but only with a 10% factor. There must be something in particular with my application and the libraries I'm using that is conflicting with audio system and/or its streams. I will update as soon as I find out.

https://src-bin.com


Answer #1

Finally, I found out what was causing the problem. I used jar-in-jar-loader (as far as I know, it's equivalent to Eclipse option "Package required libraries into generated JAR") to include library jars inside my application. Until now, this never had any noticeable impact on performance.
But with Java 8 I experience this tremendous slowdown. Monitoring the application with jconsole I noticed it was often blocked waiting for zip deflate operations, so something must have changed in JRE version 8, which is now less optimized for jars inside jars.

I resolved choosing to extract all library jars and then packaging them in my application jar.


Answer #2

Java 8 introduces some new techniques of garbage collectors. Since you are loading data/Ojects into the VM, they might be getting triggered to perform concurrent sweeps and parallel compaction. Recommend you to tune the JVM GC params.

-XX:ConcGCThreads=n Number of threads concurrent garbage collectors will use. The default value varies with the platform on which the JVM is running.

-XX:InitiatingHeapOccupancyPercent=n Percentage of the (entire) heap occupancy to start a concurrent GC cycle. It is used by GCs that trigger a concurrent GC cycle based on the occupancy of the entire heap, not just one of the generations (e.g., G1). A value of 0 denotes 'do constant GC cycles'. The default value is 45.

-XX:ParallelGCThreads=n Sets the number of threads used during parallel phases of the garbage collectors. The default value varies with the platform on which the JVM is running. -XX:ConcGCThreads=n Number of threads concurrent garbage collectors will use. The default value varies with the platform on which the JVM is running.

http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

Kindly, let me know if GC tuning helped, I am not able to replicate your scenario, but it would be an interesting fact to learn what was causing it !





java-8