Отслеживание «пропавшего» использования памяти в Linux

10

В ядре Arch 3.6.7 x86_64 я пытаюсь учесть использование памяти системой, которое, чем больше я на это смотрю, тем больше появляется дыра (в учете используемой памяти нет дыры в использование).

Это недавно загруженная система. Не так много, кроме systemd и sshd для простоты

$ ps aux | sort -n -k6
...
root       316  0.0  0.0   7884   812 tty1     Ss+  14:37   0:00 /sbin/agetty --noclear tty1 38400
matt       682  0.0  0.0  24528   820 pts/0    S+   15:09   0:00 sort -n -k6
dbus       309  0.0  0.0  17280  1284 ?        Ss   14:37   0:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
matt       681  0.0  0.0  10808  1364 pts/0    R+   15:09   0:00 ps aux
root       308  0.0  0.0  26060  1516 ?        Ss   14:37   0:00 /usr/lib/systemd/systemd-logind
root       148  0.0  0.0  25972  1692 ?        Ss   14:37   0:00 /usr/lib/systemd/systemd-udevd
matt       451  0.0  0.0  78180  2008 ?        S    14:37   0:00 sshd: matt@pts/0
root       288  0.0  0.0  39612  2708 ?        Ss   14:37   0:00 /usr/sbin/sshd -D
matt       452  0.0  0.0  16452  3248 pts/0    Ss   14:37   0:00 -bash
root         1  0.0  0.0  32572  3268 ?        Ss   14:37   0:00 /sbin/init
root       299  0.0  0.0  69352  3604 ?        Ss   14:37   0:00 /usr/sbin/syslog-ng -F
root       449  0.0  0.0  78040  3800 ?        Ss   14:37   0:00 sshd: matt [priv]
root       161  0.0  0.0 358384  9656 ?        Ss   14:37   0:00 /usr/lib/systemd/systemd-journald

Наиболее подробная информация о памяти, которую я могу найти, - это, начиная с 2007 года, которая, по-видимому, привела к добавлению поля Pss к общему ядру, учитывающему процесс, но их код на python предназначен для старых ядер и, к сожалению, некоторых файлов / proc / k * исчез с тех пор. Документация / proc / meminfo также полезна, но немного устарела .

Итак, демонстрация того, что я вижу.

# cat /proc/meminfo
MemTotal:       16345780 kB
MemFree:        16129940 kB
Buffers:           10360 kB
Cached:            48444 kB
SwapCached:            0 kB
Active:            24108 kB
Inactive:          46724 kB
Active(anon):      12104 kB
Inactive(anon):     3616 kB
Active(file):      12004 kB
Inactive(file):    43108 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:         11996 kB
Mapped:            16372 kB
Shmem:              3696 kB
Slab:              25092 kB
SReclaimable:      11716 kB
SUnreclaim:        13376 kB
KernelStack:         928 kB
PageTables:         2428 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     8172888 kB
Committed_AS:      34304 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      372788 kB
VmallocChunk:   34359362043 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       12288 kB
DirectMap2M:    16680960 kB

Если мы сложим использованные:

MemTotal - MemFree - Buffers - Cached = Used
16345780 - 16129940 - 10360 - 48444 = 157036

Все активные * / неактивные * кажутся счетчиками, применяемыми на некоторых страницах (не на всех), поэтому могут дублировать то, что считается в других местах.

Active + Inactive = Used
46724  + 24108    = 70832 (not quite)

Commited_AS здесь, похоже, тесно отслеживает сумму частной / разделяемой памяти пользовательского пространства, исключая общие файлы из / proc / * / smaps. принимая во внимание PSS также выстраивается. (Из интереса я получаю намного больше Commited_AS на 32-битном Debian 2.6.32-5-686)

AnonPages + Mapped + Commited_AS = Userspace?
11996     + 16372  + 34304       = 62672

Плита встраивается в / proc / slabinfo

Slab +  Shmem + KernelStack + PageTables = Kernelspace?
25092 + 3696  + 928         + 2428       = 32144

Userspace? + Kernelspace? = Used?
62672      + 32144        = 94816

Так что ~ 63М короче. Меня поражает, что ядру и всем загруженным модулям не хватает некоторых МБ. Плита, кажется, покрывает многое, поэтому, если что-то пропущено, я не уверен, что это будет равно ~ 60Mb?

63 немного похож на фигуру «Активный + Неактивный», но это не так.

Так кто-нибудь знает волшебную формулу ?? В противном случае, если фигура, на которую я смотрю, является правильной, какие серые области в распределении памяти я могу использовать?

Похоже, Linux съел мой баран! Хотя и меньшую часть, чем обычно обвиняют в =)

edit Commited_AS - это предположение ядра о том, сколько памяти ему понадобится для покрытия 99,9% того, что было зафиксировано, поэтому не является реальным выделенным числом. AnonPages + Mapped является его компонентом, так что теперь остается больше дыры, около 100 МБ.

User + Kernel
28368 + 32144 = 60512 != 157036

AnonPages и Mapped в основном отслеживают информацию anon / mapped из / proc / [0-9] * / smaps wgen с учетом PSS / Shared.

Зарезервированные области, кажется, все вписываются в кусок, взятый из общей памяти:

Общий объем freeпамяти составляет 16345032 КБ.
Общий объем системной памяти равен 16777216 КБ.
PCI-отверстие - lspci -v 266520 КБ = 16510696 КБ
Зарезервировано dmesg BIOS - 92793 КБ = 16417903 КБ.

edit2 Я заметил, что это дополнительное использование памяти не было на виртуальной машине , работающей внутри оригинальной коробки, из которой она /proc/meminfoбыла. Поэтому я начал ковыряться, видя, что между ними было по-другому. В конце концов обнаружилось, что увеличение общей доступной физической памяти совпало с увеличением используемой памяти.

phys 16GB used>144508     vm>50692      user>21500      kern>26428      u+ktot>47928
vm   64MB used>24612      vm>31140      user>14956      kern>14440      u+ktot>29396
vm  256MB used>26316      vm>35260      user>14752      kern>14780      u+ktot>29532
vm    1GB used>33644      vm>35224      user>14936      kern>14772      u+ktot>29708
vm    2GB used>41592      vm>35048      user>14736      kern>15056      u+ktot>29792
vm    4GB used>57820      vm>35232      user>14780      kern>14952      u+ktot>29732
vm    8GB used>82932      vm>36912      user>15700      kern>15388      u+ktot>31088
vm   12GB used>110072     vm>35248      user>14812      kern>15624      u+ktot>30436
vm   15GB used>122012     vm>35424      user>14832      kern>15824      u+ktot>30656

Получается, что на каждый 1 ГБ памяти выделяется ~ 8 МБ. Может быть, карта памяти в ядре ... но я думал, что она будет расти только по мере выделения памяти, а не настройки при загрузке.

Было бы интересно посмотреть, есть ли у кого-нибудь доступ к машинам Bigmem, если тенденция сохранится?

Matt
источник
psлежит по замыслу. Не используйте его для учета памяти.
Багамат
2
ура, но это не подсчитывает ps. Это общее использование в /proc/meminfo. Единственный учет процессов происходил через smaps, который учитывает разделяемую и личную память, но это было только для сравнения со значениями AnonPages / Mapped из meminfo.
Мэтт
linuxatemyram.com
Ханнес Шнайдермайер
отсюда и ссылка в моем посте о linux на самом деле кушает мой баран =)
Мэтт

Ответы:

3

«Память, используемая процессом» неЧеткая концепция в современных операционных системах. Что можно измерить, так это размер адресного пространства процесса (SIZE) и размер резидентного набора (RSS, сколько страниц в адресном пространстве в данный момент находится в памяти). Часть RSS является общей (большинство процессов в памяти совместно используют одну копию glibc и т. Д. Для различных других общих библиотек; несколько процессов, выполняющих один и тот же исполняемый файл, делятся этим, обрабатывают раздвоенные общие данные только для чтения и, возможно, часть еще не измененных чтение-запись данных с родителем). С другой стороны, память, используемая ядром для процесса, не учитывается, как таблицы страниц, буферы ядра и стек ядра. В общей картине вы должны учитывать память, зарезервированную для видеокарты, использование ядра и различные «дыры», зарезервированные для DOS и других доисторических систем (это не так много,

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

vonbrand
источник
1
«Память на процесс» не является четкой, но я не понимаю, почему это должно влиять на отслеживание общего использования? Что касается ядра, общие PageTables, Slab, KernelStack и другие непроцессорные счетчики mem сообщаются в / proc / meminfo и включаются в то, что я пытаюсь учесть (кажется, что там также есть запись mem процесса). В дополнение к общим счетчикам, которые я просматривал для каждого процесса, для anon / mapped, shared / private memory, чтобы получить представление о том, где память процесса может учитываться в / proc / meminfo. Я стремлюсь к тому, какой набор номеров виртуальных машин складывается с физическим, в котором у меня явно есть дыра.
Мэтт,
1
В основном psне в состоянии правильно учесть память. Так что не используйте это. Какие psотчеты были бы верны, только если бы этот процесс был единственным, запущенным в системе (это невозможно). Подробнее о том, почему вы этого не делаете, psчитайте здесь: Понимание использования памяти в Linux
bahamat