Как решено, сколько физической памяти должно быть выделено для кучи Java? - PullRequest
2 голосов
/ 28 мая 2019

У меня есть машина с 16G RAM. Я запускаю Java-приложение с аргументами -Xms9G -Xmx9G. Когда я запускаю команду top, я вижу, что мой процесс Java принимает 13,8 г VIRT , но только 4,6 г RES .

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 5019 root      20   0 13.8g 4.7g  18m S  0.7 30.7   3:28.39 java                                     

При выполнении команды pmap я вижу, что только ~ 3.9g кучи присутствует как RES , остальные 5.7g находятся в виртуальном .

Address           Kbytes     RSS   Dirty Mode   Mapping
0000000580000000 9452384 4074228 4074228 rw---    [ anon ]

Наблюдая за HPCUR с помощью jvmtop, я замечаю, что GC срабатывает, когда HPCUR достигает примерно 3g .

PID MAIN-CLASS        HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 5019 .1-SNAPSHOT.jar  408m 9216m  192m   n/a  0.25%  0.00% O8U20   webapp  823

Я заметил, что RES для процесса постепенно увеличивается , куча памяти в RES (по pmap) также постепенно увеличивается. В результате порог ГХ увеличивается.

У меня есть несколько вопросов об этом поведении.

  1. Используется только куча, которая присутствует в RES, а не VIRT?
  2. Если я выделил кучу мин 9G (-Xms), то изначально, почему выделено только 3,9 г RES. Разве это не то же самое, что поддерживать -Xms низким? Какой смысл хранить -Xms = -Xmx тогда?
  3. На каком основании принято решение, сколько кучи должно быть в RES? Где-то читал, что это управляется ОС, но какая-то грубая логика?
  4. Есть ли способ убедиться, что выделенная куча действительно используется?

Ответы [ 2 ]

2 голосов
/ 29 мая 2019
  • VIRT обозначает Виртуальную память - это все зарезервированное адресное пространство процесса. RSS - размер резидентного набора - часть виртуального адресного пространства, выделенная в физической памяти. Для любого диапазона адресов (не только кучи) RSS - это подмножество VIRT, возможно полное или пустое. Похоже, вы уже исследовали pmap - для каждого виртуального диапазона адресов отображается точный объем физически выделенной памяти (RSS).
  • ОС лениво распределяет физические страницы при первом доступе. Вот почему даже выделенная память не является частью RSS, пока соответствующие страницы не будут прочитаны или записаны. Тот факт, что большая часть кучи отсутствует в RSS, означает, что эта часть кучи никогда не затрагивалась. Смотри также этот вопрос .
  • Существует опция JVM -XX:+AlwaysPreTouch, которая принудительно затрагивает каждую страницу кучи, таким образом делая ее частью RSS. Попробуйте java -Xms9G -Xmx9G -XX:+AlwaysPreTouch.
0 голосов
/ 28 мая 2019
  1. Да HEAP - это RES (если он умещается в основной памяти)
  2. Этот ответ предполагает, что -Xms является подсказкой для GCв какой момент необходима полная сборка мусора.Тестируя с моей локальной JVM, я могу подтвердить, что он не сразу резервирует память.Что вы получаете, так это то, что ваша JVM не блокирует много неиспользуемой памяти, но быстрее достигнет нижней границы, так как меньше запусков GC.
  3. Ответил 1.: RES всегда содержит всю HEAP
  4. Насколько я понимаю, ваши варианты достигнут того, что вы намереваетесь.Ваше приложение захватит 9 ГБ памяти и затем начнет сборку мусора чаще.Есть другие опции , такие как MinHeapFreeRatio, и опции, которые зависят от используемого сборщика мусора , если вам нужна дополнительная оптимизация.

Вы печатали журналы GC ипроверить что-то не так?Если вы увидите, что GC запускается до запуска 9G, я бы посмотрел дальше.Если до попадания в 9G GC практически не запускается, я бы сказал, что все в порядке.

...