Как проанализировать фрагментацию памяти в Java? - PullRequest
13 голосов
/ 10 августа 2009

Мы испытываем несколько минут задержки на нашем сервере. Вероятно, они вызваны сборками мусора "останови мир". Но мы используем одновременную метку и очистку GC (-XX: + UseConcMarkSweepG), поэтому, я думаю, эти паузы запускаются фрагментацией памяти старого поколения.

Как можно проанализировать фрагментацию памяти старого поколения? Есть ли для этого инструменты?

Лаги случаются каждый час. В большинстве случаев они составляют около 20 секунд, но иногда - несколько минут.

Ответы [ 7 ]

6 голосов
/ 10 августа 2009

Посмотрите в документации по Java опции "java -X ..." для включения ведения журнала GC. Это скажет вам, собираете ли вы старое или новое поколение, и сколько времени занимает сбор.

Пауза "несколько минут" звучит необычно. Вы уверены, что работаете не только с слишком маленьким размером кучи, либо на машине с недостаточным объемом физической памяти?

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

  • Если вы используете большую кучу на машине с недостатком физической памяти, полный сборщик мусора может вызвать свою машинку "трэш", тратя большую часть своего времени безумно движется виртуальный Страницы памяти на диск и с диска. Вы можно наблюдать это с помощью системы инструменты мониторинга; например наблюдая вывод консоли из "vmstat 5" на типичная система UNIX / Linux.

Followup

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

Страница 1023 * Общие сведения о журналах уборщика мусора с одновременной пометкой на сайте Oracle должна помочь при интерпретации журналов GC.

Наконец, заключение ОП о том, что это проблема «фрагментации», маловероятно, и (ИМО) не поддерживается фрагментами доказательств, которые он представил. Скорее всего, что-то еще.

3 голосов
/ 10 мая 2013

Для низкоуровневого мониторинга вы захотите использовать это -XX:PrintFLSStatistics=1 (или увеличьте его до 2 при большей стоимости блокировки). Это недокументированное и иногда дает вам некоторые характеристики. К сожалению, это не очень полезно в большинстве приложений по разным причинам, но, по крайней мере, полезно для всех.

Вы должны увидеть, например,

Max Chunk Size: 215599441

и сравните с этим

Total Free Space: 219955840

, а затем оцените фрагментацию на основе средних размеров блоков и количества блоков.

0 голосов
/ 01 июня 2016

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

  • Мы застряли с использованием Java 6, в котором не было сжатого сборщика мусора
  • Наше приложение делало слишком много GC, в основном коллекция молодого поколения и какая-то большая коллекция старого поколения
  • Наш размер кучи был довольно большой - основная проблема (мы сократили, но наше приложение занимало слишком много строк и коллекций)

Проблема, которая проявилась в том, что только один конкретный алгоритм в нашей системе работал медленно; все остальные, которые работали одновременно, работали вполне нормально. Это исключило полный сборщик мусора; Также мы использовали jstat и другие инструменты j ** для проверки GC, дампов потоков + отслеживания журналов GC.

Из дампов потоков jstack, взятых в течение некоторого времени, мы могли понять, какой блок кода действительно замедляется. Так что сомнение упало на фрагментацию кучи.

Чтобы проверить, что я написал простую программу, которая инициализировала два List, один ArrayList и один LinkedList, и добавила операции, вызывающие изменение размера. Этот тест я мог выполнить через дескриптор REST. Обычно нет большой разницы. Но внутри фрагментированной кучи есть четкая разница во времени; изменение размера большой коллекции с ArrayList становится очень медленным, чем со списком связанных. Эти сроки были записаны, и другого объяснения этому не было, кроме фрагментированной головы.

С Java 7 мы перешли на G1GC вместе с большой работой по настройке и улучшению приложений GC; Здесь сжатие кучи намного лучше, и оно может обрабатывать большие кучи, хотя я предполагаю, что что-нибудь более чем 16-граммовая куча попадет вам в места, которые вы действительно не хотите - GC suckage :)

0 голосов
/ 11 декабря 2009

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

0 голосов
/ 16 сентября 2009

Виталий, Есть проблема фрагментации. Мое наблюдение: Если есть небольшие размеры объектов, которые часто обновляются, то в этом случае он генерирует много мусора. Хотя CMS собирает память, занятую этими объектами, эта память фрагментирована. Теперь в дело вступает нить Mark-Sweep-Compact (остановите мир) и попытайтесь сжать эту фрагментированную память, вызывая долгую паузу.

В противоположность этому, если размер объекта больше, он генерирует меньше фрагментированной памяти и
Mark-Swap-Compact занимает меньше времени для сжатия этой памяти. Это может привести к снижению пропускной способности, но поможет вам сократить длительную паузу, вызванную сжатием GC.

0 голосов
/ 10 августа 2009

В Java нет фрагментации памяти; во время прогона ГХ области памяти сжимаются.

Поскольку вы не видите высокой загрузки ЦП, GC также не работает. Так что что-то еще должно быть причиной ваших проблем. Вот несколько идей:

  • Если база данных вашего приложения находится на другом сервере, могут возникнуть проблемы с сетью

  • Если вы используете Windows и подключили сетевые диски, один из дисков может заблокировать ваш компьютер (опять же проблемы с сетью). То же самое верно для дисков NFS в Unix. Проверьте системный журнал на сетевые ошибки.

  • Размещает ли компьютер большое количество данных на диске? Поскольку загрузка ЦП невелика, причиной проблемы может быть то, что приложение было перенесено на диск и запуск ГХ принудительно вернул его в ОЗУ. Это займет много времени, если на вашем сервере недостаточно реальной оперативной памяти для хранения всего Java-приложения в оперативной памяти.

Кроме того, другие процессы могут вынудить приложение из оперативной памяти. Проверьте реальное использование памяти и ваше пространство подкачки.

Чтобы понять вывод журнала GC, этот пост может помочь.

[РЕДАКТИРОВАТЬ] Я все еще не могу разобраться с "низкими процессорами" и "киосками GC". Эти два обычно противоречат друг другу. Если ГХ останавливается, вы должны увидеть 100% загрузки ЦП. Если процессор простаивает, то что-то еще блокирует сборщик мусора. Есть ли у вас объекты, которые перегружают finalize()? Если финализировать блоки, GC может занять вечность.

0 голосов
/ 10 августа 2009

Я использовал YourKit для хорошего эффекта для этого типа проблемы.

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