В этом посте будет рассмотриваться процесс JVM и в общих чертах описан механизм использования им памяти.
В ОС Linux процессы не работают с памятью напрямую. Каждому процессу выделяется виртуальное пространство, к которому он обращается при необходимости. В момент непосредственного использования памяти ядро системы ассоциирует адрес в виртуальном адресном пространстве процесса со страницами памяти, которыми располагает система (физически существующей памятью). Процесс обеспечивается механизмом lazy allocation.
lazy allocation, в первом приближении, - механизм выделения памяти, подразумевающий, что пока страница памяти, выделенная в адресном пространстве пользовательского процесса, не будет запрошена, она не ассоциируется с физически существующей памятью.
Из принципа работы этого механизма: процессу/процессам ОС может быть выделено больше "виртуальной" памяти, чем физически располагает система. Подобная ситуация не всегда допустима, поэтому процессу, запрашивающему себе память в своём виртуальном адресном пространстве иногда требуется явно указать, как она будет соотносится с физической памятью системы. В связи с этим для дальнейшего понимания вывода диагностических утилит, необходимо ввести классификацию памяти.
Reserved memory - память, которая может быть будет выделена процессу. У любого процесса Reserved memory может быть больше сумы физического объёма памяти в системе.
Выделяется в виртуальном адресном пространстве без выделения физической памяти. Выделяется методом mmap с указанием ключа PROT_NONE. Т.к. страницы выделены в витр. адресном пространстве, они резервируют часть адресов этого адресного пространства и другие вызовы mmap не будут пытаться использовать уже занятые адреса, но обращния к этим страницам будет вызывать ошибку с отправкой процессу сигнала SIGSEGV.
Commited memory - память в виртуальном адресном пространстве, выделенная процессу. От reserved отличается тем, что резервируется не с флагом PROT_NONE, а, например, с PROT_READ | PROT_WRITE. Страницы commited memory, в отличие от reserved memory, не только зарезервированы в виртуальном адресном пространстве процесса, но и могут быть замаплены на физическую память системы без получения процессом SIGSEGV. При обращении к таким страницам ядро обрабатывает этот вызов, привязывая страницы памяти виртуального адресного пространства процесса и физически существующей памяти прозрачно для процесса.
Resident memory - память, выделенная процессу, в которую процесс записал что-либо.
lazy allocation, в первом приближении, - механизм выделения памяти, подразумевающий, что пока страница памяти, выделенная в адресном пространстве пользовательского процесса, не будет запрошена, она не ассоциируется с физически существующей памятью.
Из принципа работы этого механизма: процессу/процессам ОС может быть выделено больше "виртуальной" памяти, чем физически располагает система. Подобная ситуация не всегда допустима, поэтому процессу, запрашивающему себе память в своём виртуальном адресном пространстве иногда требуется явно указать, как она будет соотносится с физической памятью системы. В связи с этим для дальнейшего понимания вывода диагностических утилит, необходимо ввести классификацию памяти.
Reserved memory - память, которая может быть будет выделена процессу. У любого процесса Reserved memory может быть больше сумы физического объёма памяти в системе.
Выделяется в виртуальном адресном пространстве без выделения физической памяти. Выделяется методом mmap с указанием ключа PROT_NONE. Т.к. страницы выделены в витр. адресном пространстве, они резервируют часть адресов этого адресного пространства и другие вызовы mmap не будут пытаться использовать уже занятые адреса, но обращния к этим страницам будет вызывать ошибку с отправкой процессу сигнала SIGSEGV.
Commited memory - память в виртуальном адресном пространстве, выделенная процессу. От reserved отличается тем, что резервируется не с флагом PROT_NONE, а, например, с PROT_READ | PROT_WRITE. Страницы commited memory, в отличие от reserved memory, не только зарезервированы в виртуальном адресном пространстве процесса, но и могут быть замаплены на физическую память системы без получения процессом SIGSEGV. При обращении к таким страницам ядро обрабатывает этот вызов, привязывая страницы памяти виртуального адресного пространства процесса и физически существующей памяти прозрачно для процесса.
Resident memory - память, выделенная процессу, в которую процесс записал что-либо.
Как это соотносится с памятью (heap) процесса JVM
Resident memory
Для примера можно рассмотреть процессjava -jar /opt/gcviewer/gcviewer-1.35-SNAPSHOT.jarвывод top по этому процессу
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7284 user 20 0 5299360 210658 29432 S 0.3 1.6 0:03.74 java
Столбец RES означает, сколько памяти в данный момент используется процессом. В моём случае используется 210658 килобат. Это resident memory или по-другому RSS (Resident Set Size).
На графике использования heap из jvisualvm синяя область - это часть resident memory процесса. То есть та память, которая заполнена чем-либо.
Использующаяся часть heap - это, конечно, не вся resident memory рассматриваемого процесса. Вся resident memory процесса будет складываться из занятых Heap и Native областей.
Commited memory.
На том же графике можно увидеть, что текущий Heap size состовляет около 150 Мб.Текуций heap size JVM - это commited memory.
Текущий размер heap - это не вся commited memory рассматриваемого процесса, а её часть.
Общий объём commited memory процесса складывается из commited memory heap и native областей памяти процесса.
Reserved memory
Если запустить тот же процесс, задав размеры heap ключами -Xms512m -Xmx100G, что заведомо больше, чем есть на моём сервере,java -Xms512m -Xmx100G, -jar /opt/gcviewer/gcviewer-1.35-SNAPSHOT.jarвывод top покажет, что занимаемая процессом Resident memory практически не изменилась и составлет 219560 Кбайт
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombieНа графике jvisualvm
%Cpu(s): 2.7 us, 1.1 sy, 0.0 ni, 94.6 id, 0.9 wa, 0.4 hi, 0.3 si, 0.0 st
KiB Mem : 8075464 total, 1616492 free, 3249608 used, 3209364 buff/cache
KiB Swap: 3145724 total, 3145724 free, 0 used. 4035756 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8398 user 20 0 0.103t 219560 29464 S 0.3 2.7 0:03.79 java
Размер использующейся в Heap памяти (Resident memory) остался почти таким же, как и при предыдущем запуске - около 20 Mb.
Размер выделенной под heap Commited memory сразу после запуска составляет 512Mб. С точки зрения JVM ключ -Xms указывает, какой размер Heap должен быть выделен при старте JVM. С точки зрения OC, виртуальное адресноге пространство памяти процесса JVM, равное 512m, должно быть зарезервировано в памяти ОС.
JVM смогла запуститься без ошибок, несмотря на то, что заданная верхняя граница памяти Heap превышает количество памяти на сервере. То есть в виртуальном адресном пространстве памяти процесса было зарезервировано 100Gb, но пока эта память не используется, она никак не привязяна к физической памяти. -Xmx100G - это Reserved memory. Когда Heap (в моём примере он равен 512M) заполнится до такой степени, что JVM потребуется его увеличение, JVM запросит у ОС зарезервированную память (reserved memory).
В моём примере во время старта JVM под процесс выделяется 512mb (commited memory) и резервируется рамять в 100Gb (reserved memory). После увеличения размера heap (не графике справа) размер commited memory стал около 600 mb
Комментариев нет:
Отправить комментарий