Подтвердить что ты не робот

Как уменьшить сбой при одновременном режиме java и чрезмерное gc

В Java сбой параллельного режима означает, что параллельный сборщик не смог освободить достаточное количество пространства памяти и долговременного генеала, и он должен отказаться и позволить полностью остановить gc. очень дорого.

Я понимаю эту концепцию, но никогда не имел хорошего понимания A) что может привести к сбою при параллельном режиме и B) какое решение?.

Такая непонятность приводит меня к написанию/отладке кода без особых намеков, и часто приходится покупать вокруг этих флагов производительности от Foo до Bar без особых причин, просто нужно попробовать.

Я бы хотел узнать у разработчиков, как ваш опыт? Если вы столкнулись с такой проблемой производительности, в чем причина и как вы ее решали?

Если у вас есть рекомендации по кодированию, пожалуйста, не будьте слишком общими. Спасибо!

4b9b3361

Ответ 1

Первое, что я узнал о CMS, - это большая память, чем другие коллекционеры, что на 25-50% является хорошей отправной точкой. Это поможет вам избежать фрагментации, поскольку CMS не делает никаких уплотнений, таких как остановка мировых коллекционеров. Во-вторых, делайте то, что помогает сборщику мусора; Integer.valueOf вместо нового Integer, избавитесь от анонимных классов, убедитесь, что внутренние классы не имеют доступа к недоступным вещам (частным в внешнем классе). Чем меньше мусора, тем лучше. FindBugs, а также игнорирование предупреждений очень помогут в этом.

Что касается настройки, я обнаружил, что вам нужно попробовать несколько вещей:

-XX: + UseConcMarkSweepGC

Сообщает JVM использовать CMS в расширенном gen.

Исправьте размер вашей кучи: -Xmx2048m -Xms2048m Это предотвращает выполнение GC таких вещей, как увеличение и сжатие кучи.

-XX: + UseParNewGC

использовать параллельное, а не серийное собрание в молодое поколение. Это ускорит ваши незначительные коллекции, особенно если у вас настроен очень большой молодой ген. Большое молодое поколение, как правило, хорошо, но не больше половины старого размера.

-XX: ParallelCMSThreads = X

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

-XX: + Замечание CMSParallelRemarkEnabled по умолчанию серийно, это может ускорить процесс.

-XX: + CMSIncrementalMode позволяет приложениям запускать больше путем пассирования GC между фазами

-XX: + CMSIncrementalPacing позволяет JVM отображать изменение, как часто он собирает с течением времени

-XX: CMSIncrementalDutyCycleMin = X Минимальное количество времени, затраченного на выполнение GC

-XX: CMSIncrementalDutyCycle = X Начните с выполнения GC этого% времени

-XX: CMSIncrementalSafetyFactor = Х

Я обнаружил, что вы можете получить обычно низкую паузу, если вы настроите ее так, чтобы она в основном собиралась. Поскольку большая часть работы выполняется параллельно, вы получаете в основном обычные предсказуемые паузы.

-XX: CMSFullGCsBeforeCompaction = 1

Это очень важно. Он сообщает коллекционеру CMS, чтобы он всегда заполнял коллекцию, прежде чем она начнет новую. Без этого вы можете столкнуться с ситуацией, когда он удаляет кучу работы и снова запускается.

-XX: + CMSClassUnloadingEnabled

По умолчанию CMS позволит вашему Пермигенту расти, пока он не убьет ваше приложение через несколько недель. Это останавливает это. Ваш PermGen будет расти только тогда, если вы используете Reflection или злоупотребляете String.intern или делаете что-то плохое с загрузчиком классов или несколькими другими вещами.

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

Ответ 2

Цитата из Понимание параллельных журналов коллекционеров мусора маркировки

Ошибка параллельного режима может следует избегать путем увеличения размера генерации или инициирования CMS сбор при меньшей загрузке кучи установив CMSInitiatingOccupancyFraction до более низкое значение

Однако, если в приложении действительно есть утечка памяти, вы просто покупаете время.

Если вам нужен быстрый перезапуск и восстановление, и вы предпочитаете "быстрый способ", я бы предложил не использовать CMS вообще. Я бы придерживался '-XX: + UseParallelGC'.

От "Эргономика сборщика мусора"

Параллельный сборщик мусора (UseParallelGC) выбрасывает исключение из памяти, если чрезмерное количество времени провел сбор небольшого количества куча. Чтобы избежать этого исключения, вы можете увеличьте размер кучи. Ты можешь также задайте параметры -XX:GCTimeLimit=time-limit и -XX:GCHeapFreeLimit=space-limit

Ответ 3

Иногда OOM довольно быстро и убит, иногда страдает длинный период gc (последний раз было более 10 часов).

Мне кажется, что утечка памяти лежит в основе ваших проблем.

Сбой CMS не будет (как я понимаю) вызовет OOM. Скорее неудача CMS происходит из-за того, что JVM нужно слишком много делать слишком много коллекций, и CMS не могла идти в ногу. Одна из ситуаций, когда много циклов сбора данных происходит за короткий период, - это когда ваша куча почти заполнена.

Очень продолжительное время GC звучит странно... но теоретически возможно, если ваша машина ужасно билась. Тем не менее, длительный период повторных GCs вполне правдоподобен, если ваша куча почти полностью заполнена.

Вы можете настроить GC, чтобы отказаться, когда куча 1) при максимальном размере и 2) все еще близка к полной после завершения полного GC. Попробуйте сделать это, если вы еще этого не сделали. Он не будет излечивать ваши проблемы, но, по крайней мере, ваша JVM быстро получит OOM, что позволит быстрее перезапустить и восстановить службу.

EDIT - опция -XX:GCHeapFreeLimit=nnn, где nnn - это число от 0 до 100, что дает минимальный процент кучи, который должен быть свободным после GC. Значение по умолчанию - 2. Опция указана в метке "Самый полный список опций -XX для Java 6 JVM" . (Есть много опций -XX, перечисленных там, которые не отображаются в документации Sun. К сожалению, на странице представлено несколько сведений о том, что на самом деле делают варианты.)

Вероятно, вам стоит начать искать, есть ли у вашего приложения /webapp утечка памяти. Если это так, ваши проблемы не исчезнут, если эти утечки не будут найдены и исправлены. В долгосрочной перспективе возиться с опциями Hotspot GC не будет исправлять утечки памяти.

Ответ 4

Я обнаружил, что использование -XX:PretenureSizeThreshold=1m для того, чтобы сделать "большой" объект сразу же перемещенным в пространство, значительно сократило мои молодые GC и сбои в параллельном режиме, поскольку он не пытается сбросить количество оставшихся в живых + 1 оставшихся в живых (xmn=1536m survivorratio=3 maxTenuringThreashould=5) до завершения полного цикла CMS. Да, мое пространство для выживших велико, но примерно раз в 2 дня что-то приходит в приложении, которое будет ему нужно (и мы запускаем 12 серверов приложений каждый день для 1 приложения).