Действительно ли Committed_AS в /proc/meminfo является правильным номером для выделенной виртуальной памяти в Linux? Здесь меньше чем MemTotal-MemAvailable

Я собираю цифры для мониторинга серверов HPC и обсуждаю политику раздачи памяти (чрезмерная загрузка или нет). Я хотел показать пользователям количество виртуальной памяти, которую запрашивали их процессы (вся машина), и сколько фактически было использовано.

Я думал, что получу интересные значения из /proc/meminfo, используя поля MemTotal, MemAvailable и Committed_AS. Предполагается, что последний показывает, сколько памяти было выделено ядром, наихудшее число того, сколько памяти действительно потребуется для выполнения запущенных задач.

Но Committed_AS явно слишком мал. Это меньше, чем используемая в настоящее время память! Соблюдайте два примера систем. Один админ-сервер:

# cat /proc/meminfo 
MemTotal:       16322624 kB
MemFree:          536520 kB
MemAvailable:   13853216 kB
Buffers:             156 kB
Cached:          9824132 kB
SwapCached:            0 kB
Active:          4854772 kB
Inactive:        5386896 kB
Active(anon):      33468 kB
Inactive(anon):   412616 kB
Active(file):    4821304 kB
Inactive(file):  4974280 kB
Unevictable:       10948 kB
Mlocked:           10948 kB
SwapTotal:      16777212 kB
SwapFree:       16777212 kB
Dirty:               884 kB
Writeback:             0 kB
AnonPages:        428460 kB
Mapped:            53236 kB
Shmem:             26336 kB
Slab:            4144888 kB
SReclaimable:    3863416 kB
SUnreclaim:       281472 kB
KernelStack:       12208 kB
PageTables:        38068 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    24938524 kB
Committed_AS:    1488188 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      317176 kB
VmallocChunk:   34358947836 kB
HardwareCorrupted:     0 kB
AnonHugePages:     90112 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      144924 kB
DirectMap2M:     4988928 kB
DirectMap1G:    13631488 kB

Это примерно 1,5 ГБ по сравнению с 2,5 ГБ без кеширования. Вычислительный узел:

ssh node390 cat /proc/meminfo
MemTotal:       264044768 kB
MemFree:        208603740 kB
MemAvailable:   215043512 kB
Buffers:           15500 kB
Cached:           756664 kB
SwapCached:            0 kB
Active:         44890644 kB
Inactive:         734820 kB
Active(anon):   44853608 kB
Inactive(anon):   645100 kB
Active(file):      37036 kB
Inactive(file):    89720 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:      134216700 kB
SwapFree:       134216700 kB
Dirty:                 0 kB
Writeback:           140 kB
AnonPages:      44918876 kB
Mapped:            52664 kB
Shmem:            645408 kB
Slab:            7837028 kB
SReclaimable:    7147872 kB
SUnreclaim:       689156 kB
KernelStack:        8192 kB
PageTables:        91528 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    345452512 kB
Committed_AS:   46393904 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      797140 kB
VmallocChunk:   34224733184 kB
HardwareCorrupted:     0 kB
AnonHugePages:  41498624 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      312640 kB
DirectMap2M:     7966720 kB
DirectMap1G:    262144000 kB

Это около 47G использованных против 44G совершенных. Рассматриваемая система является кластером CentOS 7:

uname-a
Linux adm1 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

На моем рабочем столе Linux, использующем ванильное ядро, я вижу больше "разумных" цифр, когда 32G выделяется по сравнению с 15,5G в использовании. На сервере Debian я вижу 0,4G в использовании против 1,5G зафиксированных.

Может кто-то объяснить это мне? Как получить правильный номер для выделенной памяти? Это ошибка в ядре CentOS/RHEL, о которой следует сообщить?

Обновление с большим количеством данных и сравнение между системами

Список использованной / выделенной памяти для различных систем, к которым я мог получить доступ, с примечанием о типе загрузки:

  • SLES 11.4 (ядро 3.0.101-108.71-default)
    • 17,6G/17,4G, интерактивный многопользовательский HPC (например, MATLAB, GIS)
  • CentOS 7.4 / 7.5 (ядро 3.10.0-862.11.6.el7 или 3.10.0-862.14.4.el7)
    • 1.7G / 1.3G, сервер администратора, кластер mgmt, DHCP, TFTP, rsyslog,…
    • 8.6G / 1.7G, пакетная система SLURM, 7.2G RSS только для slurmdbd
    • 5.1G / 0.6G, NFS-сервер (400 клиентов)
    • 26.8G / 32.6G, 16-ядерный узел HPC, загруженный 328 (необходимо общаться с пользователем) процессы GNU R
    • 6.5G/8.1G, 16-ядерный узел HPC с 16 процессами MPI
  • Ubuntu 16.04 (ядро 4.15.0-33-generic)
    • 1.3G / 2.2G, 6-ядерный узел HPC, 6-поточное научное приложение (1.1G RSS)
    • 19.9G / 20.3G, 6-ядерный узел HPC, 6-поточное научное приложение (19G RSS)
    • 1.0G / 4.4G, 6-ядерный узел входа в систему с метаданными BeeGFS /mgmt-сервером
  • Ubuntu 14.04 (ядро 3.13.0-161-generic)
    • 0.7G/0.3G, HTTP сервер ВМ
  • Кастомная сборка (ванильное ядро ​​4.4.163)
    • 0,7G/0,04G, в основном бездействующий сервер Subversion
  • Кастомная сборка (ванильное ядро ​​4.14.30)
    • 14.2G / 31.4G, длительный рабочий стол
  • Alpine (ядро 4.4.68-0-grsec)
    • 36,8M/16,4M, некоторые (веб) сервер
  • Ubuntu 12.04 (ядро 3.2.0-89-generic)
    • 1.0G / 7.1G, какой-то сервер
  • Ubuntu 16.04 (ядро 4.4.0-112-generic)
    • 0,9G/1,9G, какой-то сервер
  • Debian 4.0 (ядро 2.6.18-6-686, 32-битная x86, очевидно)
    • 1.0G / 0.8G, какой-то надежный сервер
  • Debian 9.5 (ядро 4.9.0-6)
    • 0.4G / 1.5G, различные веб-сервисы, небольшая нагрузка, очевидно
  • Debian 9.6 (ядро 4.9.0-8-amd64)
    • 10,9G/17,7G, рабочий стол
  • Ubuntu 13.10 (ядро 3.11.0-26-generic)
    • 3.2G / 5.4G, старый рабочий стол
  • Ubuntu 18.04 (ядро 4.15.0-38-generic)
    • 6.4G / 18.3G, рабочий стол

SUnreclaim для SLES и CentOS довольно большой... От 0.5G до 1G не редкость, больше, если не время от времени очищать кэши. Но недостаточно, чтобы объяснить недостающую память в Committed_AS. У машин с Ubuntu обычно меньше 100M SUnreclaim. За исключением 14.04, у него есть маленький Committed_AS и 0.4G SUnreclaim. Упорядочить ядра по порядку довольно сложно, поскольку ядро ​​3.10 от CentOS имеет много возможностей для резервного копирования ядер 4.x. Но, кажется, есть граница между 4.4 и 4.9, которая повлияла на странно низкие значения Committed_AS. Добавленные серверы от некоторых моих коллег предполагают, что Committed_AS также предоставляет странные числа для старых ядер. Это было сломано и исправлено несколько раз?

Могут ли люди это подтвердить? Это просто ошибочное /очень неточное поведение ядра при определении значений в /proc/meminfo, или есть история ошибок (исправлений)?

Некоторые записи в списке действительно странные. Наличие одного процесса slurmdbd с RSS четыре раза Committed_AS не может быть правильным. Я испытываю желание протестировать ванильное ядро ​​на этих системах с той же рабочей нагрузкой, но я не могу вывести наиболее интересные машины из таких игр.

Я предполагаю, что ответ на мой вопрос - указатель на исправление в истории коммитов ядра, которое снова включило хорошие оценки в Committed_AS. В противном случае, пожалуйста, просветите меня;-)

3 ответа

Эти коробки не находятся под значительным давлением памяти. Ни один не пейджинг (SwapFree). Второй блок составляет ~47 ГБ, всего 250 ГБ. 200 ГБ это много, чтобы играть с.

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

  • Время отклика пользователя (приложения) ухудшается
  • Скорость вывода страниц выше, чем вам удобно
  • Убийца ООМ убивает некоторые процессы

Отношения между счетчиками памяти не интуитивны, сильно различаются между рабочими нагрузками и, вероятно, действительно понятны только разработчикам ядра. Не беспокойтесь об этом, сосредоточьтесь на измерении очевидного давления памяти.


Другие описания Comited_AS, которые недавно были в списке linux-mm, подчеркивают, что это оценка:

Committed_AS: An estimate of how much RAM you would need to make a
              99.99% guarantee that there never is OOM (out of memory)
              for this workload. Normally the kernel will overcommit
              memory. That means, say you do a 1GB malloc, nothing
              happens, really. Only when you start USING that malloc
              memory you will get real memory on demand, and just as
              much as you use. So you sort of take a mortgage and hope
              the bank doesn't go bust. Other cases might include when
              you mmap a file that's shared only when you write to it
              and you get a private copy of that data. While it normally
              is shared between processes. The Committed_AS is a
              guesstimate of how much RAM/swap you would need
              worst-case.

Вот еще один ответ исключительно о том, что он ниже «ожидаемого»:

Интересные строки из вашегоследующие:

      Active:          4854772 kB
Inactive:        5386896 kB
Active(anon):      33468 kB
Inactive(anon):   412616 kB
Active(file):    4821304 kB
Inactive(file):  4974280 kB
Mlocked:           10948 kB
AnonPages:        428460 kB
Shmem:             26336 kB
Committed_AS:    1488188 kB

(иэто просто суммы противподробности позже и представляет собой просто сумму строк с идентификатором– Я включил эти строки только для того, чтобы было легче понять.)

Какподдерживается файлом, что не вызывает никакого повышения, поэтому практически единственные вещи, которые действительно повышают вашу ценность, - это+ ++ скачки использования памяти. Это объем памяти (ОЗУ + подкачка вместе), который система должна быть в состоянии предоставить запущенным в данный момент процессам, даже если все кеши и буферы сброшены на диск.

Если процесс делает(который обычно реализуется какилиза кулисами) ядро ​​увеличится, но не будет отображаться в других цифрах, поскольку ядро ​​фактически не резервирует реальную оперативную память до тех пор, пока память фактически не будет использована процессом. (Технически ядро ​​определило диапазон адресного пространства виртуальной памяти, который будет использоваться для процесса, но отображение виртуальной памяти для ЦП указывает на заполненную нулями страницу с флагом, который означает, что если процесс пытается что-либо записать, фактическая память должна быть выделена на лету. - это позволяет процессу считывать нули из виртуального адресного пространства без сбоев в работе ЦП, но запись данных в виртуально выделенную область памяти - это действие, которое фактически выделяет память по-настоящему.) Очень часто программы выделяют больше (виртуальной) памяти, чем на самом деле . use, так что это хорошая функция, но она, очевидно, усложняет понимание статистики памяти. Кажется, что в вашей системе в основном выполняются процессы, которые не занимают много памяти, которая фактически не используется, потому что ваше значение довольно низкое по сравнению с другими значениями.

Например, моя текущая система сейчас работает следующим образом:

      MemTotal:       32570748 kB
Active:         12571828 kB
AnonPages:       7689584 kB
Mlocked:           19788 kB
Shmem:           4481940 kB
Committed_AS:   44949856 kB

Обратите внимание на огромный объем (~45 ГБ) в моей системе, несмотря на общее количество анонимных страниц, заблокированной памяти плюситого около 12 ГБ. Поскольку я использую среду рабочего стола в этой системе, я предполагаю, что у меня есть множество процессов, которые выполняются после получения/использования большого количества оперативной памяти. В этом случае разветвленный процесс теоретически может изменить всю эту память без каких-либо явных выделений памяти, и вся эта раздвоенная память подсчитывается в сторону увеличения значения. В результате значение может вообще не отражать фактическое использование системной памяти.

TL;DR: оценивается выделенная виртуальная память, которая не резервируется какой-либо файловой системой , или максимальный объем памяти, который теоретически должен быть поддержан реальным хранилищем (ОЗУ + подкачка), чтобы текущие текущие процессы продолжали работать, если ничто не выделяет больше памяти в целая система.

Однако если система взаимодействует с внешним миром, даже входящие IP-пакеты могут привести к использованию большего объема памяти, поэтому вы не можете дать никаких гарантий относительно будущего поведения системы на основе этого числа. Также обратите внимание, что память стека всегда выделяется «на лету», поэтому, даже если ни один из ваших процессовили явно выделять память, использование памяти () может все равно увеличиться, когда процессы используют больше места в стеке.

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

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

Тем не менее, я не помню, чтобы использовал данные с ядрами старше версии 4.15, поэтому я не знаю, отличалось ли историческое поведение.

Оба иофициально являются эвристиками уровня ядра, поэтому ни одному из них не следует доверять как истинному факту.

Что касается рабочих нагрузок, которые я использую для запуска, я обычно начинаю испытывать проблемы с производительностью, когда реальный объем оперативной памяти превышает примерно 150%. Однако это, очевидно, сильно зависит от вашей рабочей нагрузки. Если у вас много процессов с утечкой и достаточно подкачки, вы можете продолжать подниматься вверх без проблем с производительностью, поскольку процессы вызывают утечку оперативной памяти, а ядро ​​заменяет протекшие области оперативной памяти на подкачку. Обратите внимание, что в таких случаях без каких-либо проблем может оказаться намного больше, чем общий объем ОЗУ + подкачка.

Я бы не отключал перераспределение памяти, если вы не используете систему жесткого реального времени. И такая вещь, вероятно, тоже не должна использовать какой-либо обмен. Лично я всегда бегаю сустановлен в.

Если вы можете обеспечить достаточный объем подкачки, обычно имеет смысл увеличитьичтобы избежать задержки из-за замены. Однако важно понимать, что— это текущая выделенная память (память, запрашиваемая процессами пользовательского режима, но обычно не полностью используемая) и имеющая покрытие RAM+swap, которое должно обрабатывать все случаи, когда ни один процесс не выделяет новую память. Если только вы не используете какую-то очень экзотическую систему, несколько процессов постоянно выделяют новую память, поэтому не следует делать слишком строгие оценки будущего поведения системы. А если ваша рабочая нагрузка очень высока, текущие цифры очень мало говорят о будущем поведении системы.

В современных системах я бы сосредоточился на статистике, которая может включать в себя все самые высокие краткосрочные пики управления памятью. Я предполагаю, что хорошо сделанная программа статистики будет отслеживать события ядра черези собирать статистику в момент наибольшей нехватки памяти. Однако я не знаю ни одного статистического приложения, которое бы действительно это поддерживало. Любое статистическое приложение, которое собирает данные только за период выборки, определенный настенными часами, пропустит большинство краткосрочных всплесков использования оперативной памяти. Для математически правильных средних выборок необходим период выборки настенных часов, но понимание пиков важнее, чем наличие точных средних значений, потому что именно эти пики убивают ваши процессы/производительность, а не средние значения.

Другие вопросы по тегам