Звук Java значительно медленнее после обновления JVM 8
My Application загружает кучу аудиоклипов при запуске. Он использует java.applet.Applet.newAudioClip(URL audioFileURL)
для загрузки файлов, находящихся в одной папке. Я мог видеть, что эта функция в основном является оболочкой для получения объектов JavaSoundAudioClip
До вчерашнего дня я скомпилировал JAR с JDK 7 и запустил его с обновлением версии JRE версии 7. Затем я обновил обновление до версии 8 31.
Теперь загрузка каждого аудио занимает в десять раз больше, чем раньше (было 0,2 секунды каждый, теперь он составляет от 2 до 3 секунд)
Такое же поведение произошло в разных аппаратных конфигурациях. ОС - 64-битная Windows 7, а среда выполнения Java 7 и 8 - 32-разрядная.
Копаясь глубже в отладке, я обнаружил, что наиболее медленными методами являются AudioSystem.getAudioInputStream
, AudioSystem.isLineSupported
, AudioSystem.getLine
Формат аудио не должен быть задействован: я пробовал как OGG, так и WAV с теми же результатами.
Настройки для обоих JVM одинаковы
EDIT: даже я не мог воспроизвести проблему в небольшой программе, сделанной ad-hoc. Java 8 работает медленнее, но только с коэффициентом 10%. Должно быть что-то в особенности с моим приложением и библиотеками, которые я использую, которые противоречат аудиосистеме и/или ее потокам. Я обновлю, как только узнаю.
Ответы
Ответ 1
Наконец, я узнал, что вызвало проблему. Я использовал jar-in-jar-loader (насколько я знаю, это эквивалентно опции Eclipse "Необходимые библиотеки для пакетов в сгенерированный JAR" ), чтобы включить библиотеки библиотеки в мое приложение. До сих пор это никогда не оказывало заметного влияния на производительность.
Но с Java 8 я испытываю это огромное замедление. Наблюдая за приложением с помощью jconsole, я заметил, что он часто блокировался в ожидании операций с дефлятом zip, поэтому что-то должно было измениться в JRE версии 8, которая теперь менее оптимизирована для банок внутри банок.
Я решил решить извлечь все банки библиотеки, а затем упаковать их в свою банку приложений.
Ответ 2
В Java 8 представлены новые методы сбора мусора.
Поскольку вы загружаете данные /Ojects в виртуальную машину, они могут запускаться для выполнения параллельных разверток и параллельного уплотнения.
Порекомендуйте вам настроить параметры JVM GC.
-XX: ConcGCThreads = n Будет использоваться количество потоков, собираемых совместно сборщиками мусора. Значение по умолчанию зависит от платформы, на которой работает JVM.
-XX: InitatingHeapOccupancyPercent = n Процент (полной) загрузки кучи для запуска параллельного цикла GC. Он используется GC, которые вызывают параллельный цикл GC, основанный на заполнении всей кучи, а не только на одном из поколений (например, G1). Значение 0 означает "делать постоянные GC-циклы". Значение по умолчанию - 45.
-XX: ParallelGCThreads = n Устанавливает количество потоков, используемых во время параллельных фаз сборщиков мусора. Значение по умолчанию зависит от платформы, на которой работает JVM.
-XX: ConcGCThreads = n Количество потоков, которые будут использоваться совместно с сборщиками мусора. Значение по умолчанию зависит от платформы, на которой работает JVM.
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
Пожалуйста, дайте мне знать, помогли ли настройки GC, я не могу реплицировать ваш сценарий, но было бы интересно узнать, что было вызывая это!