Управление памятью в Java¶
Настройка оперативной памяти¶
При стриминге в памяти создается и уничтожается много объектов с данными. Поэтому рекомендуется выделять под Java memory heap не менее, чем 1/2 физической памяти сервера. Например, если объем оперативной памяти сервера составляет 32 Гб, рекомендуется выделить 16 Гб при помощи следующих настроек в файле wcs-core.properties
Настройка сборщика мусора¶
Важной частью Java VM является сборщик мусора (Garbage Collector, GS). При запуске сборщик мусора резко увеличивает нагрузку на сервер и может приостановить выполнение остальных задач, поэтому рекомендуется минимизировать его запуски при помощи следующих настроек в файле wcs-core.properties
# Use System.gc() concurrently in CMS
-XX:+ExplicitGCInvokesConcurrent
# Disable System.gc() for RMI, for 10000 hours
-Dsun.rmi.dgc.client.gcInterval=36000000000
-Dsun.rmi.dgc.server.gcInterval=36000000000
Настройка Concurrent Mark Sweep (CMS) Collector¶
Сборщик мусора Concurrent Mark Sweep (CMS) предназначен для приложений, которым требуются короткие паузы при сборе мусора и которые могут предоставить ресурсы процессора сборщику мусора, не снизив существенно производительность системы.
1. Включить CMS GC можно следующими настройками в файле wcs-core.properties (например, выделяем 24G под heap и указываем NewSize и MaxNewSize равными значениями для регулировки размера нижней и верхней границы для молодого поколения; она должна составлять от 1/4 до 1/3 максимального размера heap):
# Used CMS GC
-XX:+UseConcMarkSweepGC -Xms24g -Xmx24g -XX:NewSize=6144m -XX:MaxNewSize=6144m
# Disable heuristic rules
-XX:+UseCMSInitiatingOccupancyOnly
# Reduce Old Gen threshold
-XX:CMSInitiatingOccupancyFraction=70
# Log
-Xloggc:/usr/local/FlashphonerWebCallServer/logs/gc-core-
-XX:ErrorFile=/usr/local/FlashphonerWebCallServer/logs/error%p.log
2. После перезапуска WCS в файлах логов gc-core.log
видим результат работы сборщика мусора. Вывод может отличаться в зависимости от установленной версии Java. Например:
openjdk version "1.8.0_222":
openjdk version "12.0.2":
Настройка Z Garbage Collector (ZGC)¶
Для Java 12 доступна экспериментальная реализации сборщика мусора Z Garbage Collector (ZGC), позволяющая обеспечить низкую задержку при сборке мусора, не останавливая выполнения потоков приложения более чем на 10 миллисекунд, даже при работе с очень большими memory heap. Стоит обратить внимание, что ZGC требует больше ресурсов процессора по сравнению с CMS GC.
Пример установки ZGC с версией OpenJDK 12:
1. Установите OpenJDK 12, как описано здесь
2. Проверяем корректность установки OpenJDK 12:
java -version
openjdk 12.0.2 2019-07-16
OpenJDK Runtime Environment (build 12.0.2+10)
OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode, sharing)
3. Устанавливаем WCS (если требуется).
4. Если WCS был установлен ранее, комментируем или удаляем следующие строки в файле wcs-core.properties
-XX:+UseConcMarkSweepGC
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
Заменяем строку
на
5. Добавляем настройки в wcs-core.properties (например, выделяем 24G под heap):
- в JDK 12-15
- в JDK 16 и выше
6. Если планируется использование больших страниц памяти (hugepages), добавляем настройки:
- в JDK 12 или 14
- в JDK 15 и выше
Затем настраиваем hugepages по рекомендациям (число страниц памяти (по 2048K каждая) c запасом к выделенной памяти под heap 1,125 \* 24G \*1024 / 2M
) и добавляем необходимые параметры в автозагрузку сервера (пример для Centos):
sudo mkdir /hugepages
sudo echo "echo 13824 >/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages" >>/etc/rc.local
sudo echo "mount -t hugetlbfs -o uid=0,mode=0757 nodev /hugepages" >>/etc/rc.local
sudo chmod +x /etc/rc.d/rc.local
sudo systemctl enable rc-local.service
sudo systemctl restart rc-local.service
sudo chmod o+w /hugepages
7. После перезапуска WCS, в файлах логов gc-core.log
видна периодическая операция работы сборщика мусора. Для понимания модели работы Z Garbage Collector можно ознакомиться с
презентацией.
Настройка выделения и освобождения физической памяти на уровне системы¶
При большой нагрузке на сервер, может оказаться недостаточно областей маппинга физической памяти (memory map areas), выделяемых процессу системой по умолчанию, что может приводить к завершению работы JVM по нехватке нативной памяти. При этом лог ошибки будет содержать следующий комментарий
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 12288 bytes for committing reserved memory.
# Possible reasons:
# The system is out of physical RAM or swap space
...
Для того, чтобы предотвратить такое поведение, необходимо увеличить количество областей маппинга памяти
и перезапустить WCS.
Известные проблемы¶
1. При использовании ZGC нагрузка на процессор сервера выше, особенно в JDK 15¶
Симптомы
При обновлении JDK c 12 или 14 до 15 и использовании ZGC возрастает средняя загрузка процессора, измеренная на уровне системы (например, утилитой htop)
Решение
Для высоконагруженных серверов, если требуется минимизация задержек при сборке мусора, использовать ZGC в JDK 12 или 14
2. Логи ZGC с настройками вывода по умолчанию могут занимать много места на диске¶
Симптомы
Файлы логов gc-core*.log
занимают много места на диске