Потерянная память в 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)

Обратите внимание, что верхние отчеты 4.8G для кешированных, а не 48G и 55G, которые используются. Результат free -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 на скриншоте выше совпадают примерно с используемой памятью, но память остается используемой даже после закрытия этих приложений - даже после того, как я завершаю контейнер, который их запускает.

EDIT: Я попытался добавить некоторый своп, и произошло что-то интересное. Я добавил 30G свопа. Спустя некоторое время объем памяти, помеченный как кешированный в верхней части, увеличился с 5 до 25 ГГц. Free -m показал около 20G больше полезной памяти. Я добавил еще 10G swap, и память в кеше поднята до 33G. Если я добавлю еще 10G подкачки, я получу 6G, которые будут признаны кэшированными. Все это время используется только несколько килобайт свопа. Это как если бы ядро ​​должно было иметь соответствующий swap для каждого бита, который он распознает или сообщает как кешированный. Вот результат сверху с 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      

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

EDIT 2: Здесь приведены значения дуги * из /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

Ответ 1

Эта память, скорее всего, используется кэшем ARC ZFS и другими связанными с 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, поэтому вам может быть поражена ошибка вроде one.

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