Как заставить мой процесс JVM всегда занимать память размером x ГБ? - PullRequest
3 голосов
/ 06 августа 2020

Это связано с моим предыдущим вопросом

Я установил Xms как 512M, Xmx как 6G для одного процесса java. У меня таких процессов три.

У меня общая оперативка 32 ГБ. Из них 2 ГБ всегда заняты.

Я выполнил команду free, чтобы гарантировать, что минимум 27 ГБ свободны. Но для моей работы в любое время требовалось не более 18 ГБ.

Все работало нормально. Каждое задание занимало от 4 до 5 ГБ, но использовало от 3 до 4 ГБ. Я понимаю, что Xmx не означает, что процесс всегда должен занимать 6 ГБ

Когда другой процесс X запускается на том же сервере с другим пользователем, он занимает 14 ГБ. Затем один из моих процессов потерпел неудачу.

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

Здесь вопрос в том, как я могу заставить мою работу всегда использовать 6 ГБ и почему в этом случае выдается ошибка G C, достигнутый предел?

Я использовал visualvm для их мониторинга. И jstat тоже.

Любые советы приветствуются.

1 Ответ

3 голосов
/ 06 августа 2020

Простой ответ: -Xmx не является жестким ограничением для JVM. Он ограничивает доступную кучу до Java внутри JVM. Уменьшите свой -Xmx, и вы можете стабилизировать память процесса до размера, который вам подходит.

Длинный ответ: JVM - сложная машина. Думайте об этом как об ОС для вашего кода Java. Виртуальной машине действительно требуется дополнительная память для собственного обслуживания (например, метаданные G C), память, занятая размером стека потоков, память вне кучи (например, память, выделенная собственным кодом через JNI; буферы) и т. Д. c .

-Xmx ограничивает только размер кучи для объектов: память, которая обрабатывается непосредственно в вашем Java коде. Все остальное не учитывается этим параметром.

Есть новый параметр JVM -XX:MaxRam ( 1 , 2 ), который пытается держите всю память процесса в пределах этого лимита.

Из вашего другого вопроса:

Это многопоточность. 100 читателей, 100 писателей. Каждый из них имеет собственное подключение к базе данных.

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

Если у вас более 200 потоков , вы также платите цену: N*(Stack size), и ок. N*(TLAB size) зарезервировано в Young Gen для каждого потока (динамически изменяемый размер):

java -Xss1024k -XX:+PrintFlagsFinal 2> /dev/null | grep -i tlab

size_t MinTLABSize    = 2048
intx ThreadStackSize  = 1024

Примерно полгигабайта только для этого (и, возможно, больше)!

Размер стека потоков ( в Кбайтах). (0 означает использовать размер стека по умолчанию) [Spar c: 512; Solaris x86: 320 (было 256 в предыдущих версиях 5.0 и ранее); Spar c 64 бит: 1024; Linux amd64: 1024 (было 0 в 5.0 и ранее); все остальные 0.] - Java Параметры виртуальной машины HotSpot ; Linux x86 JDK source

Вкратце: -Xss (размер стека) значения по умолчанию зависят от среды виртуальной машины и ОС.

Буферы локального распределения потоков являются более сложными и помогают избежать конфликтов выделения / блокировки ресурсов. Объяснение настройки здесь для их функции: Размещение TLAB и TLAB и анализируемость кучи .

Дополнительная литература: "Native Отслеживание памяти « и Q:« Java с использованием гораздо большего объема памяти, чем размер кучи »

, почему в этом случае выдается ошибка G C, достигнут предел.

«Превышен предел накладных расходов G C» . Вкратце: каждый цикл G C потреблял слишком мало памяти, и решение проблемы эргономики было отменено. Вашему процессу требуется больше памяти.

Когда другой процесс X запускается на том же сервере с другим пользователем, он занимает 14g. Затем один из моих процессов потерпел неудачу.

Еще один момент, связанный с последовательным запуском нескольких процессов с большой памятью, примите во внимание следующее:

java -Xms28g -Xmx28g <...>;
# above process finishes
java -Xms28g -Xmx28g <...>; # crashes, cant allocate enough memory

Когда первый процесс завершится, ваш ОС требуется некоторое время для обнуления памяти, освобожденной конечным процессом, прежде чем она сможет передать эти области физической памяти второму процессу. Для выполнения этой задачи может потребоваться некоторое время, и до тех пор вы не сможете запустить другой «большой» процесс, который немедленно запрашивает полные 28 ГБ кучи (наблюдается в WinNT 6.1). Это можно обойти с помощью:

  • Уменьшить -Xms, чтобы распределение происходило позже во время жизни 2-го процесса
  • Уменьшить общее -Xmx куча
  • Отложить запуск второго процесса
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...