Поощрять JVM к GC, а не наращивать кучу? - PullRequest
19 голосов
/ 18 марта 2011

(обратите внимание, что когда я говорю «JVM», я действительно имею в виду «горячую точку» и запускаю последнее обновление Java 1.6.)

Пример ситуации:

Моя JVMработает с -Xmx, установленным на 1 ГБ.В настоящее время в куче выделено 500 МБ, из которых 450 МБ используется.Программа должна загрузить еще 200 мб в кучу.В настоящее время в куче находится «собираемый» мусор на 300 Мб (предположим, что это все в самом старшем поколении.)

При нормальной работе JVM увеличит кучу до 700 Мб или около того, исборщик мусора, когда он доходит до него.

В этой ситуации мне хотелось бы, чтобы JVM сначала собрала gc, а затем распределила новый материал, чтобы в итоге мы получили размер кучи, равный 500 МБ,используемая куча в 350 МБ.

Есть ли параметр JVM, который делает это?

Ответы [ 4 ]

12 голосов
/ 18 марта 2011

Можно попробовать указать -XX:MinHeapFreeRatio и -XX:MaxHeapFreeRatio для управления расширением и сжатием кучи:

  • -XX:MinHeapFreeRatio - когда процент свободного пространства в поколении падает ниже этого значения, поколение будетбыть расширен для удовлетворения этого процента.По умолчанию установлено значение 40.
  • -XX:MaxHeapFreeRatio - когда процент свободного пространства в поколении превысил это значение, поколение будет сокращаться для достижения этого значения.По умолчанию 70.

Вы также можете поэкспериментировать с одновременным сбором мусора, указав -XX:+UseConcMarkSweepGC.В зависимости от вашего приложения размер кучи может быть меньше за счет дополнительных циклов ЦП.

В противном случае JVM будет использовать указанную вами память как доступную, когда это оптимально сделать.Вы можете указать меньшее количество, например -Xmx768m, чтобы оно содержалось, и оно могло нормально работать, хотя вы бы увеличили риск нехватки памяти в сценарии с большой нагрузкой.На самом деле единственный способ использовать меньше памяти - написать код, который использует меньше памяти:)

10 голосов
/ 30 января 2015

В HotSpot есть четыре (на самом деле, пять) разных сборщика мусора, и у вас разные варианты для каждого.

  • Последовательный коллектор имеет -XX:MinHeapFreeRatio и -XX:MaxHeapFreeRatio, что позволяет вам более или менее напрямую контролировать поведение. У меня нет большого опыта работы с серийным коллектором.
  • Параллельный коллектор (-XX:+UseParallelOldGC) имеет -XX:MaxGCPauseMillis=<millis> и -XX:GCTimeRatio=<N>. Установка более низкого максимального времени паузы обычно приводит к уменьшению размера кучи. Однако, если время паузы уже мало, куча не станет меньше. OTOH, если максимальное время паузы установлено слишком низким, приложение может тратить все свое время на сбор. Установка более низкого отношения времени gc также обычно делает кучу меньше. Вы говорите сборщику, что готовы выделить больше процессорного времени для сбора в обмен на меньшую кучу. Тем не менее, это всего лишь подсказка и может не иметь никакого эффекта. На мой взгляд, параллельный коллектор практически не работает для минимизации размера кучи. Этот сборщик работает лучше (он настраивается сам), если вы дадите ему некоторое время поработать, а поведение приложения останется неизменным.
  • Коллектор CMS (-XX:+UseConcMarkSweepGC) обычно требует большей кучи для достижения своей главной цели - малое время паузы, поэтому я не буду это обсуждать.
  • Новый коллектор G1 (-XX:+UseG1GC) не так умственно отстал, как старые коллекторы. Я считаю, что он сам выбирает меньший размер кучи. У него много настроек, хотя я только начал их изучать. -XX:InitiatingHeapOccupancyPercent, -XX:G1HeapWastePercent, -XX:G1ReservePercent и -XX:G1MaxNewSizePercent могут представлять интерес.

Посмотрите официальную документацию для сборщиков мусора, а также этот список флагов .

2 голосов
/ 18 марта 2011

Вы можете, как обычно, вызывать метод System.gc() перед выделением дополнительных 200 МБ объектов, но это будет просто подсказкой для JVM, что он может или не может следовать, и в любом случае вы не будете знать, когда это произойдет.... как указано в документации, это лучший запрос.

Кстати, учтите, что сборка мусора - тяжелая операция, поэтому, если в этом нет особой необходимости, просто не пытайтесь форсироватьit.

Просто чтобы знать: если вы установите -Xmx1G, то вы сообщаете JVM, что 1 ГБ - это максимальное пространство для кучи, и, поскольку вы указываете это, я не понимаю, почему это должностарайтесь держать его на низком уровне, если он знает, что 1 ГБ будет все еще в порядке (мы находимся в контексте языков с управлением памятью).Если вы не хотите, чтобы куча так сильно увеличивалась, просто уменьшите максимальное значение, чтобы он был вынужден выполнить GC перед выделением новых объектов, в противном случае, почему вы говорите ему использовать 1 ГБ?

0 голосов
/ 19 марта 2011

Я бы порекомендовал взглянуть сюда:

http://www.petefreitag.com/articles/gctuning/

...