2015-06-06 3 views
4

После попытки множества различных настроек JVM GC и проведения большого тестирования, когда у меня были проблемы с длинными крупными GC-паузами, я сейчас тестирую G1GC JVM GC. Помимо этого, я также собираю данные с монитором производительности, и только приложения, которые работают (помимо системных служб, ...), - это сервер GlassFish с моим приложением. Я не нашел ничего странного в протоколе мониторинга производительности (использование процессора составляет около 5-10%, и оно становится немного выше, когда происходит GC, память составляет около 60%, ...). Это теперь пятый день тестирования, и я заметил следующее:JVM GC работает очень странно

enter image description here

До второй крупный (смешанный) GC не произошло все было хорошо (второстепенный GC было около 20мс долго, производительность GC был 160000M/с, ...) , Второй крупный GC занял около 2 секунд (длинные - первые заняли 150 мс, но не критические), и после этого младший GC намного дольше, чем раньше (см. Серые линии на изображении, которые представляют продолжительность младшего (молодого) GC) и производительность GC составляет всего 12000 М/с и все еще падает. Мне интересно, почему это происходит после второго основного GC, даже никаких других приложений не работает, а использование ЦП/памяти такое же, как раньше. Я не знаю, что здесь происходит. У меня также есть еще один вопрос: я выполняю те же тесты на разных ПК, у которых меньше оперативной памяти и более старых процессоров, а производительность GC составляет около 5000 М/с (младший GC составляет около 50-100 мс), что я считаю нормальным из-за худшего процессора и меньше оперативной памяти. Странно то, что основной GC еще не состоялся после 3 дней работы, и старое поколение растет намного медленнее, чем здесь, даже настройки одинаковы. Почему растет намного медленнее (здесь около 150 МБ за два дня, на втором ПК 80 МБ за три дня)? Спасибо за все ваши ответы, я не знаю, почему GC работает так ненормально (сначала она работает нормально, а затем ухудшается производительность).

EDIT: here является лог-файл полный GC, который был импортирован в GCViewer, а также детали события статистика из GCViewer:

enter image description here

Вход на 3-й основной GC:

2015-06-08T08:09:13.123+0200: 572815.533: [GC concurrent-root-region-scan-start] 
2015-06-08T08:09:13.139+0200: 572815.560: [GC concurrent-root-region-scan-end, 0.0271771 secs] 
2015-06-08T08:09:13.139+0200: 572815.560: [GC concurrent-mark-start] 
2015-06-08T08:09:16.302+0200: 572818.721: [GC concurrent-mark-end, 3.1612900 secs] 
2015-06-08T08:09:16.318+0200: 572818.729: [GC remark 572818.729: [Finalize Marking, 0.0002590 secs] 572818.729: [GC ref-proc, 0.4479462 secs] 572819.177: [Unloading, 3.2004912 secs], 3.6499382 secs] 
[Times: user=0.20 sys=0.08, real=3.64 secs] 

Опять же, реальная время было намного выше, чем пользователь + sys, фаза разгрузки заняла более 3 секунд.

+0

Пожалуйста, опишите, что же цвета означают и какие это растущие линии. И можем ли мы увидеть длительность основного GC здесь? Если да, то где они? – AdamSkywalker

+0

Можете ли вы предоставить необработанные журналы GC для интересующего периода времени? также убедитесь, что вы вошли в журнал с помощью '-XX: + PrintGCDetails' – the8472

+0

Хорошо, фиолетовая линия - это пожизненное (старое) поколение, синие линии - это куча (так в основном молодое поколение, потому что оно начинается от линии старого поколения) вместе, серые линии внизу незначительные GC-времена, основные GC-времена (параллельные коллекции для старого поколения, а не полные GC) - это две желтые линии, где размер кучи падает (сначала занял 0,1 с и почти почти 2 секунды). Этот график из приложения GCViewer. Я сразу же загружу необработанные журналы GC. – user4341206

ответ

1

Не могу дать вам подтвержденное объяснение без глубокого погружения в проблему, но давайте попробуем.

Вы, скорее всего, прочитали документацию G1 GC oracle и знаете, что этот сборщик был создан для приложений с огромной кучей. Он был разработан для уменьшения длительных пауз во время крупных сборщиков мусора.

В вашем примере мы видим, что незначительные GC-паузы увеличиваются сразу после завершения основного GC. Я не знаю внутренней механики G1, но интуиция говорит мне, что второй крупный GC был внутренним «сигналом» для G1, чтобы анализировать его производительность (достигает ли он целей пропускной способности/приостанавливает цели). Поэтому мне кажется, что после этого анализа G1 решил изменить свои внутренние параметры. Бьюсь об заклад, что длительная незначительная пауза GC указывает на то, что G1 увеличивает пространство для молодых поколений.

Почему он это сделал? Ну, большее молодое поколение уменьшит скорость продвижения до старшего поколения. Таким образом, пространство старого поколения будет заполнено медленнее. Скорее всего, G1 попытался предотвратить следующую серьезную паузу GC, которая будет длинной, как предыдущая (2 секунды).

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

Как насчет вашей «медленной» машины, которая работала 3 дня без серьезной паузы GC - это действительно сложно сказать, не зная конфигурации GC и того, как работает ваше приложение. Держу пари, что загрузка приложения была ниже.

+0

Благодарим вас за ответ. То, что вы написали, имеет смысл, потому что младший GC длиннее - поэтому пространство старого поколения будет заполнено медленнее, я думаю, что это можно увидеть и из графика (фиолетовая линия растет медленнее, чем раньше). Я не думаю, что. Да, я прочитал документацию обо всех GC, и я также попробовал их, но у меня были длительные паузы со всех них, кроме G1GC (http://stackoverflow.com/questions/30566779/jvm-gc-problems). Я также использовал монитор производительности, но я не нашел ничего полезного. Возможно, G1GC также попытался предотвратить серьезный GC на более медленной машине, как здесь ... – user4341206

+0

Но если GC действительно решил, что означает, что производительность и производительность GC будут ниже (сейчас производительность GC примерно на 20% ниже, пропускная способность на данный момент составляет всего 0,02%). Мне действительно интересно, сколько времени займет последний крупный GC.Не могли бы вы также рассказать мне, если вы порекомендуете мне не использовать G1GC для моего сервера из-за небольшого размера кучи? Если да, то можете ли вы рассказать мне, какие настройки использовать с CMS, чтобы получить меньшее время паузы (см. Мой другой вопрос, какую ссылку я разместил в предыдущем комментарии? Спасибо ... – user4341206

+1

Как было упомянуто @ the8472, вы можете дать G1 цель паузы указав флаги. Я не упомянул об этом в ответ, потому что думал, что вы уже это сделали. В любом случае, я прочитал ваш второй вопрос, чтобы получить более подробную информацию. Для кучи 512 Мб у вас огромный гигантский GC. Это не проблема GC Я уверен, что проблема заключается в 1) на сервере Glassfish 2) Windows-инструментах. Я бы попробовал Tomcat/переключение на Linux. У меня был реальный опыт, когда счетчики производительности Windows резко замедлили приложение. – AdamSkywalker

1

Поскольку вы, похоже, беспокоитесь о временах паузы, я не вижу никаких целей времени паузы в ваших флагах JVM.

Вы можете установить время паузы времени через MaxGCMinorPauseMillis (только для несовершеннолетних) и MaxGCPauseMillis (в целом).

Это просто цели, сборщик может не встретить их по разным причинам. По умолчанию GC разрешено записывать только 1% вашего процессорного времени на GCing. Поэтому, если не удается выполнить свои цели, вы можете попробовать установить GCTimeRatio=19, чтобы предоставить ему 5% времени (обмен пропускной способностью на паузу).


Самая длинная пауза в журналах, кажется, это одна:

2015-06-05T09:14:51.909+0200: 317539.613: [GC remark 317539.613: [Finalize Marking, 0.0003625 secs] 317539.613: [GC ref-proc, 0.9890475 secs] 317540.602: [Unloading, 0.9739555 secs], 1.9643775 secs] 

Вы можете попробовать низведение контрольного времени обработки с -XX:+ParallelRefProcEnabled

+0

Я попытался установить MaxGCPauseMillis с CMS, но это не помогло (хотя были длинные паузы, хотя) ... С G1GC MaxGCPauseMillis установлено значение по умолчанию 200 мс, поэтому я удалил флаг MaxGCPauseMillis, потому что я хочу использовать эту настройку по умолчанию. Я попробую с GCTimeRatio = 19, я до сих пор не слышал об этом варианте. – user4341206

+0

обновил мой ответ – the8472

+0

Спасибо, я тоже буду использовать этот флаг. Это должно уменьшить время ref-proc, если я правильно понял - что касается времени разгрузки класса, есть ли флаг, чтобы уменьшить это время тоже? – user4341206