Похоже, вы не получили достаточную кучу JVM. Конечно, рабочий набор может поместиться в 1 Гбайт, но вам все равно нужно дать ему больше. Чтобы понять, почему, читайте дальше.
Предположим, что при выполнении сборщик мусора, он делает количество работы W1
, которое пропорционально количеству не-мусора, который он просматривает, чтобы идентифицировать мусор и другой объем работы W2
, которая пропорциональна количество мусора, которое он находит. (На самом деле, это немного сложнее, чем это ... но давайте держать анализ простым.)
Предположим, что у вас есть куча 1Gb кучи с 0.9Gb, занятая доступными объектами. Каждый раз, когда GC запускается, он может восстановить не более 0,1 Гбайт кучного пространства, и при этом ему необходимо выполнить W1 * 0.9Gb + W2 * 0.1Gb
работы. Объем работы на один байт, обработанный, равен (W1 * 0.9Gb + W2 * 0.1Gb)/0.1Gb
; т.е. 9 * W1 + W2
.
Теперь предположим, что у вас есть куча 2Gb с 0.9Gb, занятая доступными объектами. Теперь количество исправленных работ на байт составляет (W1 * 0.9Gb + W2 * 1.1Gb)/1.1Gb
или W1 * 9/11 + W2
.
Если вы сравните эти два, вы увидите, что GC делает примерно W1 * 8
больше работы за каждый байт, исправленный в куче 1Gb по сравнению с кучей 2Gb.
Как правило, чем ближе к полному вы запускаете кучу, тем более неэффективным будет сборщик мусора.Уроки:
Настройка виртуальной машины Java, чтобы использовать щедрое кучу, и
Настройка виртуальной машины Java, чтобы бросить OOM, если есть меньше, чем (скажем) 25% от кучи бесплатно после запуска полный GC.
И вот я и собирался дать советы о том, как приятно приветствовать их, и дать им совет на Рождество. –
@Pekka: пожалуйста, объясните ... – JRL
@JRL Он думал о человеке, управляющем грузовиком. – bmargulies