Потерянная память в Linux - не кешируется, не буферизируется

Мой сервер Ubuntu 12 таинственным образом теряет/тратит память. Он имеет 64 ГБ оперативной памяти. Около 46 ГБ отображаются как использованные, даже когда я закрываю все свои приложения. Эта память не используется для буферов или кэширования.

Результат top (пока мои приложения работают, приложения используют около 9G):

top - 21:22:48 up 46 days, 10:12,  1 user,  load average: 0.01, 0.09, 0.12
Tasks: 635 total,   1 running, 633 sleeping,   1 stopped,   0 zombie
Cpu(s):  0.2%us,  0.2%sy,  0.0%ni, 99.6%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65960100k total, 55038076k used, 10922024k free,   271700k buffers
Swap:        0k total,        0k used,        0k free,  4860768k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                         
  5303 1002      20   0 26.2g 1.2g  12m S    0  1.8   2:08.21 java                                                                                                                                             
  5263 1003      20   0  9.8g 995m 4544 S    0  1.5   0:19.82 mysqld                                                                                                                                           
  7021 www-data  20   0 3780m  18m 2460 S    0  0.0   8:37.50 apache2                                                                                                                                          
  7022 www-data  20   0 3780m  18m 2540 S    0  0.0   8:38.28 apache2      
  .... (smaller processes)

Обратите внимание, что top сообщает о кэшировании 4,8 ГБ, а не о 48 ГБ, а используется 55 ГБ. Результат бесплатного -m:

             total       used       free     shared    buffers     cached
Mem:         64414      53747      10666          0        265       4746
-/+ buffers/cache:      48735      15678
Swap:            0          0          0

Что использует мою память? Я перепробовал все возможные диагностики. Форумы переполнены людьми, задающими один и тот же вопрос, потому что Linux использует оперативную память для буферов/кеша. Кажется, это не то, что здесь происходит.

Может иметь значение, что система является хостом для контейнеров lxc. Первые и свободные результаты, о которых сообщалось выше, относятся к хосту, но в контейнерах сообщается об аналогичном использовании памяти. Остановка всех контейнеров не освобождает память. Некоторые 46G остаются в использовании. Однако, если я перезапущу хост, память будет свободна. Он не достигает 46G раньше времени. (Я не знаю, это занимает дни или недели. Это занимает больше, чем несколько часов.)

Также может иметь значение, что система использует zfs. Zfs считается прожорливым к памяти, но не настолько. Эта система имеет две файловые системы zfs на двух пулах raidz, один на 1,5T и один на 200G. У меня есть еще один сервер, который демонстрирует точно такую ​​же проблему (46G ничем не используется) и настроен почти так же, но с массивом 3T вместо 1,5T. У меня есть много снимков (около 100) для каждой файловой системы zfs. Обычно у меня есть один снимок каждой файловой системы, смонтированной в любое время. Их размонтирование не возвращает мне память.

Я вижу, что числа VIRT на снимке экрана выше примерно совпадают с используемой памятью, но память остается используемой даже после закрытия этих приложений — даже после закрытия контейнера, в котором они запущены.

РЕДАКТИРОВАТЬ: я попытался добавить своп, и произошло кое-что интересное. Я добавил 30G подкачки. Спустя несколько мгновений объем памяти, помеченной как кэшированная вверху, увеличился с 5G до 25G. Free -m указывает примерно на 20 ГБ больше полезной памяти. Я добавил еще 10G подкачки, а кеш-память увеличил до 33G. Если я добавлю еще 10G подкачки, я получу еще 6G, распознаваемых как кешированные. За все это время сообщается об использовании лишь нескольких килобайт подкачки. Это как если бы ядру нужно было иметь соответствующий своп для каждого бита, который он распознает или сообщает как кешированный. Вот вывод top с 40G подкачки:

top - 23:06:45 up 46 days, 11:56,  2 users,  load average: 0.01, 0.12, 0.13
Tasks: 586 total,   1 running, 585 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65960100k total, 64356228k used,  1603872k free,   197800k buffers
Swap: 39062488k total,     3128k used, 39059360k free, 33101572k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                         
 6440 1002      20   0 26.3g 1.5g  11m S    0  2.4   2:02.87 java                                                                                                                                             
 6538 1003      20   0  9.8g 994m 4564 S    0  1.5   0:17.70 mysqld                                                                                                                                           
 4707 dbourget  20   0 27472 8728 1692 S    0  0.0   0:00.38 bash      

Любые предложения высоко ценятся.

РЕДАКТИРОВАТЬ 2: вот значения arc* из /proc/spl/kstat/zfs/arcstats

arc_no_grow                     4    0
arc_tempreserve                 4    0
arc_loaned_bytes                4    0
arc_prune                       4    0
arc_meta_used                   4    1531800648
arc_meta_limit                  4    8654946304
arc_meta_max                    4    8661962768

L2ARC не активирован для ZFS


person David Bourget    schedule 15.09.2013    source источник
comment
Вы поняли это? У меня нет подсказок, но я хотел бы знать, что вызывает это!   -  person Guido    schedule 10.01.2014


Ответы (1)


Эта память, скорее всего, используется кэшем ZFS ARC и другими данными, связанными с ZFS, хранящимися в памяти ядра. Кэш ARC чем-то похож на буферный кеш, поэтому о нем, как правило, нечего беспокоиться, поскольку эта память освобождается ZFS, если на нее есть спрос.

Однако между буферной кэш-памятью и ARC-кэшем есть небольшая разница. Первый сразу доступен для выделения, а кэш ARC — нет. ZFS отслеживает доступную свободную оперативную память и, когда ее становится слишком мало, освобождает оперативную память для других потребителей.

Это отлично работает с большинством приложений, но меньшинство из них либо сбиты с толку, когда сообщается о низком объеме доступной оперативной памяти, либо выделяют слишком много/слишком быструю память для процесса выпуска, чтобы не отставать от нужного темпа.

Вот почему ZFS позволяет уменьшить максимальный размер, который может использовать размер ARC. Эта настройка выполняется в файле /etc/modprobe.d/zfs.conf.

Например, если вы хотите, чтобы размер ARC никогда не превышал 32 ГБ, добавьте следующую строку:

options zfs zfs_arc_max=34359738368

Чтобы получить текущий размер ARC и другую различную статистику ARC, выполните следующую команду:

cat /proc/spl/kstat/zfs/arcstats

Метрика size покажет текущий размер ARC. Имейте в виду, что другие области памяти, связанные с ZFS, также могут занимать часть оперативной памяти и не обязательно будут быстро освобождаться, даже если они больше не используются. Наконец, ZFS в Linux, безусловно, менее зрелая, чем собственная реализация Solaris, поэтому вы можете столкнуться с ошибкой, подобной этой один.

Также обратите внимание, что из-за конструкции общего пула хранения размонтирование файловой системы ZFS не освобождает никаких ресурсов. Вам нужно будет экспортировать пул для освобождения памяти.

person jlliagre    schedule 15.09.2013
comment
Джиллиагре: Я должен был сказать, что у меня были ошибки нехватки памяти (что и привлекло мое внимание к этому). Так что либо ZFS плохо себя ведет, либо это не так. Я не могу найти, как проверить объем памяти, используемый ZFS. В выводе memstat нет явно соответствующей строки. - person David Bourget; 15.09.2013
comment
Спасибо. Я не уверен, как читать значения arcstats. Если предположить, что они выражены в байтах, похоже, что ARC использует только 1,5G. См. РЕДАКТИРОВАТЬ 2. - person David Bourget; 15.09.2013
comment
Опубликуйте значения c_min, c_max и size вместе с настройками, представленными в zfs.conf (если есть). - person jlliagre; 15.09.2013
comment
В Ubuntu 16.04 мне нужно было запустить update-initramfs -u -k all перед перезагрузкой, чтобы распространить эти настройки из /etc/modprobe.d/zfs.conf. - person lechup; 15.07.2017