У меня проблема с виртуальным размещенным сервером под управлением CentOS. В прошлом месяце процесс (на основе java), который работал нормально, начал испытывать проблемы с получением памяти при запуске JVM.
Я заметил одну странную вещь: когда я запускаю процесс, PID сообщает, что он использует 470 МБ ОЗУ, в то время как «использованная» память сразу уменьшается более чем на 1 ГБ. Если я запускаю «сверху», общее количество ресурсов RES, используемых во всех процессах, будет меньше «использованного», указанного вверху, почти на 700 МБ.
Сотрудник службы поддержки говорит, что это означает, что у меня утечка памяти в моем процессе. Я не знаю, чему верить, потому что я ожидал бы, что утечка памяти просто потратит впустую память, выделенную процессу, а не потребляет дополнительную память, которая не отображается с помощью 'top'.
Я разработчик, а не серверный парень, поэтому обращаюсь к экспертам. Для меня, если общая память RES не соответствует общему количеству «использованных», это означает, что что-то не так с настройкой моего виртуального сервера. Должен ли я подозревать в этом случае утечку памяти в java-процессе?
Если я использую free
перед:
total used free shared buffers cached
Mem: 2097152 149264 1947888 0 0 0
-/+ buffers/cache: 149264 1947888
Swap: 0 0 0
free
после:
total used free shared buffers cached
Mem: 2097152 1094116 1003036 0 0 0
-/+ buffers/cache: 1094116 1003036
Swap: 0 0 0
Таким образом, похоже, что процесс использует (или вызывает использование) около 1 ГБ ОЗУ. Поскольку процесс (на основе top
используется только 470 МБ, значит ли это, что ядро внезапно использует дополнительные 500 МБ?
Изменить: добавлен вывод cat proc/meminfo
- при запущенном java-приложении:
MemTotal: 2097152 kB
MemFree: 1112672 kB
Buffers: 0 kB
Cached: 0 kB
SwapCached: 0 kB
Active: 0 kB
Inactive: 0 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 2097152 kB
LowFree: 1112672 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 0 kB
Mapped: 0 kB
Slab: 0 kB
PageTables: 0 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
CommitLimit: 0 kB
Committed_AS: 0 kB
VmallocTotal: 0 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 2048 kB
Поле "использовано" в top
отражает общий объем используемой оперативной памяти, в том числе процессами, файловыми буферами и кешем. Но число RES показывает только объем оперативной памяти, используемой процессом, за исключением файловых буферов.
Чтобы действительно увидеть, сколько ОЗУ используется без буферов, используйте free
команду и посмотрите на -/+ buffers/cache
линия. Число в столбце «используется» показывает, сколько оперативной памяти фактически используется процессами.
Вот пример:
$ free
total used free shared buffers cached
Mem: 2057196 1812352 244844 0 344768 833660
-/+ buffers/cache: 633924 1423272
Swap: 2097148 0 2097148
Эти выходные данные показывают, что в системе 2 ГБ оперативной памяти, из которых используется 1,8 ГБ. Однако 344 МБ из них используется буферами, а 833 МБ - кешем. Если вычесть это, останется только 633 МБ, используемых процессами и ядром.
Запустить free
до и после запуска вашего Java-приложения, чтобы лучше понять, что происходит.
Изменить: удалены ссылки на память ядра, о которой эти инструменты не сообщают.
Не позволяйте кешу и нулям подкачки беспокоить вас, поскольку это хост VPS.
Кэширование и подкачка ввода-вывода, вероятно, обрабатываются базовым хостом виртуализации, и они, вероятно, решили, что подкачка и кеширование ввода-вывода в гостевых системах с их настройкой налагает снижение производительности или что-то в этом роде, что может быть хорошо, поскольку это означает, что вы получите 2 ГБ RAN только для своих процессов. Обычно инженеры хостинг-провайдера знают, что делают.
Это также может быть причиной того, что вещи не совсем складываются, поскольку из-за того, как ваш VPS заключен в тюрьму (если они используют что-то вроде OpenVZ), вы можете не увидеть все вещи, которые используют вашу оперативную память, вверху, но они необходимы для запуска ваших процессов и, таким образом, учитываются в вашей квоте.
Кроме того, вы не получите полной картины, если все, что вы сравниваете, - это ваш единственный процесс Java, поскольку ваше приложение может запускать дополнительные процессы, даже их множество, которые складываются. Такой объем памяти, который не учитывается, может легко быть утечкой памяти приложения Java. Скорее всего, это порождает процессы и выделяет оперативную память, не возвращая их обратно в ОС.
Ваше приложение запускает или использует какой-либо собственный процесс? Создает ли он другие процессы или потоки?