Оригинал: https://web.archive.org/web/20120520221529/http://emilics.com/blog/article/mconsumption.html
Примечание переводчика: статья написана в 2012 году, когда RSS считался так, как пишет автор. В настоящий момент в выводе программ вроде ps используется PSS, которая обозначается как RSS. Если вы запустите скрипт на питоне, ссылка на который есть в статье, то получите значение, которое совпадает с RSS в современной системе.
В статье рассказывается об объективном методе оценки потребления памяти процессом в Линукс. В Линукс имеется менеджер виртуальной памяти, поэтому определить, сколько памяти потребляет один процесс, не так просто, как многие думают. В статье объясняется, что означает каждый индикатор потребления памяти.
Вывод для тех, кому некогда читать
Я считаю объективной метрику PSS(Proportional Set Size) для оценки потребления памяти, если ваша линукс-система её поддерживает. Функция на Питоне, приведённая ниже, возвращает PSS для процесса с заданным ID в кибибайтах (1 Kib=1024 байт). Если она не работает, то, вероятно, ваша операционная система не отображает PSS.
import sys, re
def pss_of_process(pid):
with file('/proc/%s/smaps' % pid) as fp:
return sum([int(x) for x in re.findall('^Pss:\s+(\d+)', fp.read(), re.M)])
Вот ссылка на скрипт pss.py, который выводит список процессов и значение PSS для них: https://web.archive.org/web/20130227090134/http://emilics.com/media/pub/pss.py
Чтобы увидеть значения PSS для всех запущенных в пространстве пользователя процессов, выполните команду:
% sudo python pss.py
Вывод команды (на машине переводчика):
admin 1116 934 /bin/sh /usr/bin/startx
admin 1160 909 sh /home/admin/wmaker.sh
messagebus 950 737 /usr/bin/dbus-daemon --system
admin 1146 549 /usr/bin/dbus-daemon --syslog --fork --print-pid 5 --print-address 7 --session
admin 3233 481 /usr/bin/dbus-daemon --config-file=/usr/share/defaults/at-spi2/accessibility.conf --nofork --print-
admin 1155 459 wmsystemtray
admin 1145 446 dbus-launch --exit-with-session /usr/bin/wmaker
root 1089 371 dhcpcd: [privileged proxy] wlan0 [ip4]
dhcpcd 3138 333 dhcpcd: wlan0 [ip4]
root 1063 318 /sbin/agetty 38400 tty3 linux
Программа распространяется под лицензией BSD.
Аллегория, чтобы понять идею
В статье объясняется значение трёх индикаторов, которые можно использовать для определения размера потребляемой одним процессом памяти в Линукс. Это VSZ (Virtual Memory Size) - размер виртуальной памяти, RSS (Resident Set Size) - размер резидентной памяти, и PSS (Proportional Set Size) - пропорциональный размер резидентной памяти.
Хоть аналогия будет неточной, давайте рассмотрим следующий пример, чтобы понять смысл индикаторов: три человека живут в одной комнате. Будем считать, что каждый человек - это процесс, а стоимость проживания - потребление памяти. В этой аналогии потребление памяти одним процессом будет соответствовать расходам на оплату комнаты для одного человека.
У каждого жильца свой сотовый телефон, и расходы на сотовую связь они оплачивают отдельно. Все три индикатора - VSZ, RSS, PSS, - будут учитывать расходы на сотовую связь для каждого индивидуально, здесь проблем нет.
Вместе с комнатой сдаётся гараж, который можно использовать, если за него заплатить. Но у всех троих нет машины, и они им не пользуются. Тем не менее, VSZ будет добавлять всю стоимость гаража каждому в расходы, даже если человек им не пользуется. То есть VSZ - это расходы на проживание, включая все доступные опции, независимо от их фактического потребления. RSS и PSS учитывают только фактические расходы и, соответственно, не будут учитывать стоимость неиспользуемого гаража.
Все трое пользуются одним шлюзом для интернета и кабельным телевидением, поэтому делят затраты между собой. В этом случае RSS будет добавлять полную стоимость интернета и TV каждому жильцу, даже если стоимость поделена между ними. RSS устроен так, чтобы подсчитывать расходы, будто они ни с кем не разделены.
PSS будет добавлять в оплату проживания каждому треть стоимости интернета и телевидения, поскольку счёт делится между всеми жильцами. Эта метрика более объективна, чем RSS, так как учитывает то, что расходы поделены.
Давайте немного усложним аналогию, чтобы понять ограничения для PSS. Один из жильцов много сидит в интернете, а телевизор смотрит мало, поэтому они договорились, что он оплачивает 50% стоимости интернета и 20% телевидения. PSS не учитывает подобные ситуации и просто делит затраты на интернет и телевидение поровну - каждому третью часть.
Я считаю, что PSS - наиболее объективная метрика, хотя у неё есть свои ограничения, и в некоторых ситуация RSS предпочтительней - в случае, если вы хотите узнать, сколько будете платить, если съедете с комнаты и будете жить одни.
Управление виртуальной памятью
В старые добрые времена узнать количество потребляемой одним процессом памяти для операционных систем типа MS-DOS или µITRON было просто. Однако в современных системах всё сложнее, поскольку они снабжены менеджером виртуальной памяти, который даёт множество преимуществ, но при этом усложняет расчет используемой памяти для одного процесса.
Менеджер виртуальной памяти в Линукс имеет ряд важных функций, связанных с измерением потребления памяти. Прежде чем перейти к их объяснению, давайте посмотрим результат команды ps aux, которая выдаёт информацию о процессах (Прим. переводчика: это вывод с моей машины).
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 2480 1752 ? Ss 12:26 0:00 init [3]
root 2 0.0 0.0 0 0 ? S 12:26 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< 12:26 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< 12:26 0:00 [rcu_par_gp]
root 5 0.0 0.0 0 0 ? I< 12:26 0:00 [slub_flushwq]
root 6 0.0 0.0 0 0 ? I< 12:26 0:00 [netns]
root 8 0.0 0.0 0 0 ? I< 12:26 0:00 [kworker/0:0H-events_highpri]
root 10 0.0 0.0 0 0 ? I< 12:26 0:00 [mm_percpu_wq]
В странице руководства man ps написано следующее:
RSS - объём резидентной памяти - памяти, которую использует процесс, не считая выгруженной в своп. Алиас rsz.
VSZ - объём виртуальной памяти процесса в кибибайтах. Device mapper на данный момент не учитывается, алиас vsz.
Какую метрику использовать: RSS или VSZ? Далее будет объяснено, как работают оба эти индикатора, а также PSS (Proportional Set Size). Команда ps не отображает PSS, но его можно найти в файловой системе /proc.*
*Примечание переводчика: конкретно в /proc/$pid/status, где оно называется теперь RSS.
Технические термины:
Страница - блок памяти, которым оперирует менеджер памяти в Линукс. Как правило, её размер составляет 4096 байт.
Физическая память - реальная память - как правило, RAM, - которая имеется в компьютере.
Виртуальная память - память, выделяемая под процесс. Процесс считает, что у него своя собственная непрерывная память, изолированная от других процессов, независимо от объёма физической памяти компьютера и от того, сколько ещё процессов на неё претендуют. Страницы виртуальной памяти отображаются в физические страницы и, таким образом, процессы оперируют только виртуальной памятью.
VSZ и Demand Paging
Использовать метрику vsz для измерения памяти, потребляемой процессом, не имеет особого смысла из-за функции Demand Paging - загрузка страниц в память при обращении к ним, - которая предотвращает ненужное потребление памяти.
Например, функционал текстового редактора emacs позволяет работать с XML-файлами. Однако, большую часть времени эта функция не используется, поэтому нет смысла загружать её в физическую память, если пользователю надо отредактировать обычный текст. Demand Paging не даёт загружать страницы, к которым процесс не обращается. Функция работает следующим образом: при запуске программы Линукс выделяет процессу виртуальную память, но не загружает в физическую память страницы, к которым она не обращается в данный момент. Когда программа вызывает функцию из виртуальной памяти, модуль управления памятью процессора - MMU - сообщает ОС, что страница не загружена. Тогда Линукс приостанавливает выполнение процесса, загружает страницу в физическую память, после чего снова запускает процесс. При этом процессу не нужно знать, что он был приостановлен - он просто полагает, что функция загружена в память, и использует её.
VSZ (virtual memory size) показывает размер всей виртуальной памяти процесса, независимо от того, загружены страницы в физическую память или нет. Таким образом, это не объективный показатель потребления памяти, включающий в себя фактически не используемые страницы.
RSS (Resident Set Size) и разделяемые библиотеки
RSS показывает общее количество страниц процесса, загруженных в физическую память. Может показаться, что это и есть настоящий объём потребляемой процессом памяти, и что эта метрика лучше, чем VSZ, но всё не так просто из-за разделяемых (динамических) библиотек.
Библиотека - это модуль, который программы используют для реализации определённого функционала. Например, libpng.so занимается сжатием и распаковкой изображений в формате PNG, а libxml2.so - обработкой файлов XML. Чтобы программистам каждый раз не писать эти функции, можно пользоваться библиотеками, которые уже написаны.
Разделяемый объект - это библиотека, которой одновременно пользуются несколько программ или процессов. Пусть у нас запущено одновременно два процесса, которым требуется функционал библиотеки libxml2.so. Чтобы не загружать несколько раз одинаковые страницы памяти, Линукс загружает один экземпляр библиотеки в физическую память и отображает его в виртуальную память обоих процессов. Процессам неважно, используют ли они функцию совместно, так как они получают доступ к ней в своей виртуальной памяти. Разделяемые библиотеки позволяют не дублировать страницы в памяти.
А теперь вернёмся к примеру про emacs, который может работать с файлами в формате XML благодаря библиотеке libxml2.so. На этот раз пользователю на самом деле нужно открыть файл XML в emacs, поэтому emacs использует libxml2.so. Тем временем в фоне выполняются ещё два процесса, использующие ту же библиотеку. Поскольку она разделяемая, Линукс загружает один её экземпляр в физическую память и отображает его в виртуальную память всех трёх процессов.
Если вы посмотрите метрику RSS для emacs, то в неё будут включены страницы libxml2.so. RSS не врёт, потому что emacs действительно её использует, но как насчёт двух других процессов, обращающихся к библиотеке? Если вы сложите RSS всех трёх процессов, то libxml2.so будет учтена три раза, хотя в физическую память загружен только один экземпляр.
Таким образом, RSS - это индикатор для случаев, когда процесс работает один и не использует никаких функций совместно с другими процессами. На практике, где разделяемые библиотеки используются совместно, RSS будет завышать показатель памяти, потребляемой одним процессом. Эту метрику можно использовать для оценки потребления памяти, но надо иметь в виду данную особенность.
PSS (Proportional Set Size)
Индикатор PSS используется для измерения объёма памяти, потребляемой одним процессом, который делит объём памяти, потребляемой страницами разделяемых объектов, поровну между процессами, которые их используют. RSS считает объём памяти следующим образом: если N процессов используют одну разделяемую библиотеку, то каждый процесс потребляет часть памяти этой библиотеки, равную 1/N.
Например, emasc и ещё два процесса совместно используют библиотеку libxml2.so. Так как процесса три, то каждый использует 1/3 объёма памяти, занимаемой libxml2.so.
Я считаю, что PSS - более объективный индикатор, чем RSS. Особенно он подходит для учёта памяти, потребляемой всей системой, а не каждым процессом в отдельности. Например, если вы разрабатываете систему со множеством процессов и служб и хотите оценить, сколько памяти надо установить в устройство, то PSS покажет более точный результат, чем RSS.