Успокаивание возбужденного сборщика мусора - PullRequest
3 голосов
/ 17 февраля 2010

У меня есть программа, которая очень хорошо работает с -Xmx2g. С -Xmx1g оно останавливается. Это никогда не приводит к исключению нехватки памяти - или, по крайней мере, у меня никогда не было терпения ждать достаточно долго.

Это говорит о том, что общий объем не вмещается в 1 г, но у GC есть некоторая тревога о возможном исчерпании пространства.

Объем памяти - это комбинация некоторых крупных, стабильных предметов с большим количеством эфемерного трафика.

Имеет ли какой-либо из более или менее неясных вариантов GC отношение к этой ситуации?

Ответы [ 4 ]

4 голосов
/ 17 февраля 2010

Существует множество параметров, которые вы можете установить в JVM для сборки мусора с помощью http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html. Когда приложение останавливается из-за GC, вы обычно видите много крупных сборок, которые могут остановить все, когда собирают. Вы можете настроить параметры младшего и основного сбора, чтобы узнать, можно ли использовать более частые второстепенные сборы.

Я рекомендую взглянуть на то, что поглощает кучу, используя инструмент, подобный VisualVM (поставляется с JDK6, я думаю, обновление 7+), и проанализировать графы объектов. Также обратите внимание на инструменты для анализа файла hprof ( Как мне проанализировать файл .hprof? ).

3 голосов
/ 17 февраля 2010

Похоже, вы не дали достаточно кучу JVM. Конечно, рабочий набор может умещаться в 1 Гбайт, но вам все равно нужно дать больше. Чтобы понять почему, читайте дальше.

Предположим, что когда работает сборщик мусора, он выполняет объем работы W1, который пропорционален количеству не мусора, который он сканирует для идентификации мусора, и другого объема работы W2, который пропорционально количеству мусора, который он находит. (На самом деле, это немного сложнее, чем это ... но давайте сделаем анализ простым.)

Предположим, что у вас есть куча 1Гб кучи с 0,9Гб, занятой достижимыми объектами. Каждый раз, когда GC запускается, он может освободить не более 0,1 Гб пространства кучи, и при этом ему необходимо выполнить W1 * 0.9Gb + W2 * 0.1Gb работы. Объем работы на один восстановленный байт составляет (W1 * 0.9Gb + W2 * 0.1Gb) / 0.1Gb; то есть 9 * W1 + W2.

Теперь предположим, что у вас есть куча 2 ГБ с 0,9 ГБ, занятые достижимыми объектами. Теперь объем работы на один восстановленный байт равен (W1 * 0.9Gb + W2 * 1.1Gb) / 1.1Gb или W1 * 9/11 + W2.

Если вы сравните эти два значения, вы увидите, что сборщик мусора выполняет примерно на W1 * 8 больше работы на байт, возвращаемой в куче 1 Гб, по сравнению с кучей 2 Гб.

Как правило, чем ближе к полной вы запускаете кучу, тем более неэффективным будет сборщик мусора. Уроки:

  • настроить JVM для использования щедрой кучи и

  • настроить JVM на выдачу OOM, если после выполнения полного GC осталось менее 25% свободного места в куче.

2 голосов
/ 17 февраля 2010

Во многих случаях для OOME может потребоваться действительно длительное время.Это потому, что, когда GC начинает усердно работать, он останавливает все действия в вашей программе.Если вы обычно получаете, например, 1 секунду полезного программного времени на каждые 0,01 с времени GC, в этих случаях вы можете увидеть, что оно полностью перевернуто - 0,01 с полезного программного времени на каждые 1 с времени GC.При такой скорости может потребоваться смехотворно много времени, чтобы съесть последние 512 Кб кучи объемом 1 ГБ.

VisualVM и его плагин VisualGC - ваши друзья;их графики будут показывать различные закономерности, когда вы находитесь в таком состоянии.

0 голосов
/ 17 февраля 2010

Если вы не хотите выполнять тонкую настройку, вам следует проверить параметры MinHeapFreeRatio и MaxHeapFreeRatio среди других, описанных здесь Java SE 6 HotSpot [tm] Настройка сборки мусора виртуальной машины это может привести к к «эффекту транквилизатора».

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