2011-01-21 2 views
6

Я заметил, что при воспроизведении звука в java этап MarkSweepCompact в gc слишком длинный и приводит к коротким периодам молчания, что неприемлемо. Поэтому мне нужно использовать низкую паузу gc. Я пробовал Parallel и CMS, они, похоже, работают лучше, потому что я полагаю, что пауза короче, и они не выполняют полную коллекцию так часто, как по умолчанию.Настройка звукового сопровождения GC для Java

До сих пор я проверил свою программу со следующими параметрами для ParallelGC:

-XX:+UseParallelGC 
-XX:MaxGCPauseMillis=70 

и ConcurrentMarkSweep:

-XX:+UseConcMarkSweepGC 
-XX:+CMSIncrementalMode 
-XX:+CMSIncrementalPacing 

Я также попытался G1GC, но это все еще экспериментальная в Java 6. Варианты для обоих режимов:

-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 

Какой GC лучше в этой ситуации? Может ли любой из этих параметров быть оптимизирован для лучшей производительности процессора и минимального использования памяти?

EDIT Признать паузу я время записи для записи аудиоданных на выходной линии, как правило, это от 92 до 120 мс (я пишу 16384 байт = ~ 92ms), объявление, когда Full GC запускается, это 200+ мс:

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 распределения шаблон для моего приложения является следующее: он загружает кучу объектов при запуске, то он начинает играть, и я предполагаю, что большинство объектов после этого выделяется графическим интерфейсом, потому что просмотр/приостановка звука не сильно меняет график GC. Это то, что visualgc показывает с параллельным gc: alt text

График начинается при запуске, и я начинаю воспроизведение. Меченые являются

1) задержки звука и полный дс, я думаю, что он вырос старый размер:

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) открыть окно приложения и паузы воспроизведения. Ничего не меняется, немного позже он увеличивает размер eden.

3) Я открываю окна и снова запускаю воспроизведение.

Так что мне нужно увеличить размер старого генерала? Как мне это сделать? Я работаю с -XX: NewRatio = 10 и -XX: NewSize = 10m

Спасибо.

ответ

5

Лог, который вы предоставляете, слишком мал, чтобы обеспечить реальный анализ, но он говорит, что он потратил 200 мс на то, что старый ген в основном полон. Это означает, что ваша куча слишком мала или у вас есть утечка памяти. В этой ситуации мало что можно сделать для настройки алгоритма GC. Поэтому остальная часть этого ответа касается того, как вы можете получить больше информации из приложения и/или как настроить GC, как только вы устраните утечку памяти или получите большую кучу.

В значительной степени низкая пауза означает делать все возможное, чтобы коллекции были собраны только в виде молодых коллекций.

Вам действительно нужно регистрироваться, когда вы начинаете и заканчиваете писать, а затем сопоставляете это с паузами STW, которые происходят в JVM в течение этого периода, иначе вы действительно не знаете, что может вызвать проблему или насколько серьезной проблема является.

Вещи, которые я сделал бы немедленно;

  1. изменить ваш каротаж, так что вы выводите в одной строке легко распознаваем скрипт (возможно время_запуска, время окончания, длительность)
  2. добавить PrintGCApplicationStoppedTime и PrintGCApplicationConcurrentTime переключатели, так что вы получите запись каждый STW паузы а не только GC события
  3. использовать последнюю версию виртуальной машины Java (т.е. 6u23), поскольку было много улучшений в горячих точках за последний год или два, так что точка, используя более старый один
  4. Вы не говорите, если вы re ограничено памятью, но я определенно увеличил бы с размером кучи, если можете, 40M довольно мало, поэтому у вас недостаточно места для игры с
  5. Запуск приложения с помощью visualgc, он дает более полное представление о том, что происходит на IMO, поскольку у вас есть все разные виды вверх в один раз

Главное - определить, где у вас заканчивается пространство и почему. Ответ на это, вероятно, заключается в том, какова структура распределения вашего приложения, является ли это генерированием нагрузки короткоживущих объектов, так что вы быстро сжигаете свой крошечный облик? слишком высокий порог владения, так что вы подвергаете ping ponging объектам через оставшиеся в живых пространства до того, как они все равно будут перенаправлены и, таким образом, вынуждают частые длинные gcs (медленные)?

Несколько других вещей, которые нужно иметь в виду ...

  • iCMS (incremental) предназначен для использования на 1 или 2 основных машинах, описывает ли это вашу машину? сколько ядер у вас есть? вы можете просто хотите отказаться от такой вариант
  • CMS имеет один резьбовую фазу (INIT знак), это может быть больно вам
  • CMS обычно предпочитает большую кучу, чем у других коллекционеров, ваш довольно мал

Редактировать после графика visualgc, добавленного к вопросу Поскольку вы ограничены в памяти, вам необходимо наилучшим образом использовать пространство, которое у вас есть, единственный способ сделать это - повторить бенчмаркинг ... идеально с повторяемым контрольная работа.

  • Вы можете использовать -Xmn, чтобы указать размер молодого поколения, остаток будет предоставлен на хранение.
  • вы можете настроить свое использование оставшихся в живых пространствах, так что вы позволяете им получить более полными, прежде чем они поменялись местами, и пусть объекты там живут дольше, прежде чем они получают ординарный
    • -XX:TargetSurvivorRatio=90 устанавливает его так выжившее пространство должны чтобы быть на 90% заполненным до того, как он будет скопирован, очевидно, что между стоимостью копирования и использованием пробела существует
    • -XX:+PrintTenuringDistribution, чтобы показать размер каждого места и то, что происходит, вы также можете увидеть это в visualgc
    • использовать -XX:+MaxTenuringThreshold, чтобы указать, сколько раз объект может пережить юную коллекцию (скопируйте из одного оставшегося в прошлое пространство в другое) bef руда, т.е. если вы знаете, что вы получите только короткоживущий мусор или вещи, которая живет вечно, то установка этого 1 имеет смысл
  • вы должны понимать, что запуская ординарные коллекции и, возможно, рассмотреть вопрос о принятии мер, чтобы сделать его запустить позже
    • для CMS это может включать в себя настройку -XX:CMSInitiatingOccupancyFraction=<value>, например установлен на 80, и это вызовет CMS при 80% занятости (NB: это плохо, чтобы ошибиться, поэтому вы можете предпочесть разрешить хот-спот управлять этим, установить его слишком маленьким и собирать слишком часто, убивая производительность, устанавливая его слишком большой, и это может вызвать слишком поздно вызывая незапланированную полную коллекцию соответственно долгого время паузы
  • , если это действительно старые коллекции, которые причиняют вам боль, и вам нужно низкая пауза затем использовать CMS и ParNew

Наконец, получите профилировщик и выясните, откуда идет мусор, вы можете обнаружить, что легче контролировать скорость, с которой создается мусор, а затем выливать усилие в черную дыру, которая может быть настроена на GC!

+0

Да, я ограничен памяти, это аудиоплеер, он не должен использовать более 30-40 Мб. Как правило, моя куча примерно наполовину заполнена. –

+0

visualgc - отличный инструмент, спасибо, я обновил вопрос с помощью графика visualgc. –

3

Это означает, что слишком много объектов объектов продвигаются из пространства с эденом, так как основному GC не нужно много разбираться. Вы можете увеличить отношение пространства к новым поколениям с помощью -XX: NewRatio. Попробуйте 10 и двигайтесь вверх.
Еще лучше изучите, как можно уменьшить область действия объектов, на которые ссылаются объекты в вашей программе.

1

ОК, словом, у вас есть нефункциональное требование к системе, которая не указана для удовлетворения этого требования. «Правильный» ответ заключался бы в использовании реализации JVM в режиме реального времени. Но большинство из них дорогие, и я предполагаю, что вы согласитесь на правильное решение на 99,9%.

Первое, что вы должны сделать, это найти способ измерения этих прерываний. В противном случае любой эксперимент по сопоставлению различных сборщиков мусора обречен быть ненадежным.

После этого введения заявления, давайте прийти к вашей проблеме:

Вы сказали, что сборщик мусор вводят паузы в звуковом воспроизведении. Ваши варианты:

  1. Улучшите сборщик мусора, используя более подходящие варианты.
  2. Создать меньше мусора.
  3. Периодически вызывать сборщик мусора, но это может очень хорошо привести к обратному эффекту. Вы должны измерить!
  4. Используйте методы скрытия задержки, чтобы уменьшить влияние пауз, вызванных сборщиком мусора.

Завершить: если вы действительно хотите избавиться от этой проблемы, (1) найти способ ее измерения, (2) провести эксперименты, (3) найти основную причину, (4) решить первопричиной и (5) мерой, которую вы действительно решили.

+0

Я использую jconsole для мониторинга gc, и я экспериментирую прямо сейчас. –

+0

Вы можете записать звук и графики в visualvm или jconsole, чтобы узнать, что происходит во время пробелов в звуковом выходе? – jmg

+0

вместо записи звука, я записываю время, необходимое для записи звука в выходную строку, см. Мое редактирование. –

1

Я знаю, что это старый вопрос и OP, вероятно, даже не интересует больше, но меня беспокоит, что эти строки были в его конфигурации:

-XX:MaxHeapFreeRatio=10 
-XX:MinHeapFreeRatio=10 

Для меня это означает, что его виртуальная машина будет пытаться ПОСТОЯННО запросить память из системы или освободить ее - я уверен, что между этими двумя цифрами должен быть разрыв.

Кроме того, для тех, кто пытается сделать систему Java в реальном времени, трюк состоит в том, чтобы выделить ВСЕ ваши объекты спереди, а затем никогда ничего не выделять.

Это может быть сложно, но это невозможно для длинного выстрела - включите -verbose: gc и просто удалите «Новые» и другие вещи, которые выделяют память, пока вы вообще не увидите никаких gcs.

В GUI, между прочим, это означает создание всех ваших элементов GUI и никогда их не освобождать, просто скрывать и показывать. Это также означает отсутствие строковых манипуляций (используйте только StringBuffers и строковые константы - это самая трудная задача для решения, потому что так много системных вызовов полагаются на строки)

+0

Привет. Да, я вообще отказался от этого проекта, но спасибо за ваш ответ. Я установил эти два параметра, чтобы минимизировать объем памяти приложения. Я полагаю, что установка их на одно и то же значение может привести к изменению размера кучи на каждом gc, что увеличивает время gc. В настоящее время я настроен на 20/10. И он все еще держит память :( –

+0

И то, что я сделал в конце концов, заключалось в том, чтобы свести к минимуму количество длинных живых объектов и сделать большие пространства для жизни и жизни более крупными, чтобы как можно меньше объектов добраться до старого поколения. –

+0

Да, java, кажется, любит память .. Я натолкнулся на это, пытаясь свести к минимуму след, а не паузы ... У меня есть один 10gb tomcat, который делает мою машину dev серьезно несчастной. Одна вещь, которую я заметил, когда Я установил его на 10/20, это не помогло, так как когда я установил его на 20/40, я думаю, что есть какой-то нижний предел, после которого он начинает просто игнорировать nubmers (конечно, конечно). –