Как измерить фактическое использование памяти приложения или процесса? - PullRequest
664 голосов
/ 25 сентября 2008

Этот вопрос охватывается здесь очень подробно.

Как вы измеряете использование памяти приложением или процессом в Linux?

Из статьи в блоге Понимание использования памяти в Linux , ps не является точным инструментом для этой цели.

Почему ps является "неправильным"

В зависимости от того, как вы на это смотрите, ps не сообщает о реальном использовании памяти процессами. Что он действительно делает, так это показывает, сколько реальной памяти каждый процесс занял бы , если бы это был единственный процесс, выполняющий . Конечно, на типичном компьютере с Linux в каждый момент времени выполняется несколько десятков процессов, а это означает, что номера VSZ и RSS, сообщаемые ps, почти определенно неверны .

Ответы [ 31 ]

19 голосов
/ 29 сентября 2008

На этот вопрос нет однозначного ответа, поскольку вы не можете точно определить объем памяти, используемый процессом. Большинство процессов в Linux используют разделяемые библиотеки. Например, предположим, что вы хотите вычислить использование памяти для процесса 'ls'. Вы считаете только память, используемую исполняемым файлом 'ls' (если бы вы могли ее изолировать)? Как насчет libc? Или все эти другие библиотеки, необходимые для запуска 'ls'?

linux-gate.so.1 =>  (0x00ccb000)
librt.so.1 => /lib/librt.so.1 (0x06bc7000)
libacl.so.1 => /lib/libacl.so.1 (0x00230000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00162000)
libc.so.6 => /lib/libc.so.6 (0x00b40000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00cb4000)
/lib/ld-linux.so.2 (0x00b1d000)
libattr.so.1 => /lib/libattr.so.1 (0x00229000)
libdl.so.2 => /lib/libdl.so.2 (0x00cae000)
libsepol.so.1 => /lib/libsepol.so.1 (0x0011a000)

Можно утверждать, что они используются другими процессами, но «ls» не может быть запущен в системе без их загрузки.

Кроме того, если вам нужно знать, сколько памяти требуется процессу для планирования емкости, вам необходимо рассчитать, сколько использует каждая дополнительная копия процесса. Я думаю, что / proc / PID / status может дать вам достаточно информации об использовании памяти за один раз. С другой стороны, valgrind предоставит вам лучший профиль использования памяти на протяжении всей жизни программы

16 голосов
/ 08 сентября 2010

Если ваш код написан на C или C ++, вы можете использовать getrusage(), который возвращает вам различные статистические данные об использовании памяти и времени вашего процесса.

Хотя не все платформы поддерживают это и будут возвращать 0 значений для параметров использования памяти.

Вместо этого вы можете посмотреть на виртуальный файл, созданный в /proc/[pid]/statm (где [pid] заменен идентификатором вашего процесса. Вы можете получить его из getpid()).

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

12 голосов
/ 04 января 2010

Valgrind может отображать подробную информацию, но это значительно замедляет целевое приложение и в большинстве случаев меняет поведение приложения.
Exmap - это то, чего я еще не знал, но, похоже, вам нужен модуль ядра для получения информации, которая может быть препятствием.

Полагаю, что все хотят знать, как WRT использует память:
В Linux объем физической памяти, который может использовать отдельный процесс, можно условно разделить на следующие категории.

  • M.a анонимно отображенная память

    • .p частный
      • .d dirty == malloc / mmapped куча и стек выделены и записана память
      • .c clean == malloc / mmapped куча и память стека после выделения, записи, освобождения, но еще не восстановления
    • .s поделился
      • .d dirty == malloc / mmaped heap может копироваться при записи и совместно использоваться процессами (отредактировано)
      • .c clean == malloc / mmaped heap может копироваться при записи и совместно использоваться процессами (отредактировано)
  • M.n именованная отображенная память

    • .p частный
      • .d dirty == файл mmapped записанной памяти private
      • .c clean == сопоставленный текст программы / библиотеки private mapped
    • .s поделился
      • .d dirty == файл mmapped совместно используемая записанная память
      • .c clean == отображенный общий текст библиотеки, отображенный

Утилита, включенная в Android под названием showmap , весьма полезна

virtual                    shared   shared   private  private
size     RSS      PSS      clean    dirty    clean    dirty    object
-------- -------- -------- -------- -------- -------- -------- ------------------------------
       4        0        0        0        0        0        0 0:00 0                  [vsyscall]
       4        4        0        4        0        0        0                         [vdso]
      88       28       28        0        0        4       24                         [stack]
      12       12       12        0        0        0       12 7909                    /lib/ld-2.11.1.so
      12        4        4        0        0        0        4 89529                   /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
      28        0        0        0        0        0        0 86661                   /usr/lib/gconv/gconv-modules.cache
       4        0        0        0        0        0        0 87660                   /usr/lib/locale/en_US.utf8/LC_MEASUREMENT
       4        0        0        0        0        0        0 89528                   /usr/lib/locale/en_US.utf8/LC_TELEPHONE
       4        0        0        0        0        0        0 89527                   /usr/lib/locale/en_US.utf8/LC_ADDRESS
       4        0        0        0        0        0        0 87717                   /usr/lib/locale/en_US.utf8/LC_NAME
       4        0        0        0        0        0        0 87873                   /usr/lib/locale/en_US.utf8/LC_PAPER
       4        0        0        0        0        0        0 13879                   /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
       4        0        0        0        0        0        0 89526                   /usr/lib/locale/en_US.utf8/LC_MONETARY
       4        0        0        0        0        0        0 89525                   /usr/lib/locale/en_US.utf8/LC_TIME
       4        0        0        0        0        0        0 11378                   /usr/lib/locale/en_US.utf8/LC_NUMERIC
    1156        8        8        0        0        4        4 11372                   /usr/lib/locale/en_US.utf8/LC_COLLATE
     252        0        0        0        0        0        0 11321                   /usr/lib/locale/en_US.utf8/LC_CTYPE
     128       52        1       52        0        0        0 7909                    /lib/ld-2.11.1.so
    2316       32       11       24        0        0        8 7986                    /lib/libncurses.so.5.7
    2064        8        4        4        0        0        4 7947                    /lib/libdl-2.11.1.so
    3596      472       46      440        0        4       28 7933                    /lib/libc-2.11.1.so
    2084        4        0        4        0        0        0 7995                    /lib/libnss_compat-2.11.1.so
    2152        4        0        4        0        0        0 7993                    /lib/libnsl-2.11.1.so
    2092        0        0        0        0        0        0 8009                    /lib/libnss_nis-2.11.1.so
    2100        0        0        0        0        0        0 7999                    /lib/libnss_files-2.11.1.so
    3752     2736     2736        0        0      864     1872                         [heap]
      24       24       24        0        0        0       24 [anon]
     916      616      131      584        0        0       32                         /bin/bash
-------- -------- -------- -------- -------- -------- -------- ------------------------------
   22816     4004     3005     1116        0      876     2012 TOTAL
9 голосов
/ 29 июля 2009

Valgrind удивителен, если у вас есть время, чтобы запустить его. valgrind --tool=massif - правильное решение.

Однако я начинаю запускать большие примеры, и использование valgrind больше не практично. Есть ли способ определить максимальное использование памяти (размер страницы по модулю и общие страницы) для программы?

В реальной системе Unix /usr/bin/time -v работает. В Linux, однако, это не работает.

9 голосов
/ 09 октября 2012

Я использую htop; это очень хорошая консольная программа, похожая на Windows Task Manager.

9 голосов
/ 02 мая 2016

Еще три способа попробовать:

  1. ps aux --sort pmem
    Сортирует вывод по %MEM.
  2. ps aux | awk '{print $2, $4, $11}' | sort -k2r | head -n 15
    Сортировка с использованием труб.
  3. top -a
    Начинается сортировка сверху по %MEM

(Извлечено из здесь )

8 голосов
/ 09 августа 2011
#!/bin/ksh
#
# Returns total memory used by process $1 in kb.
#
# See /proc/NNNN/smaps if you want to do something
# more interesting.
#

IFS=$'\n'

for line in $(</proc/$1/smaps)
do
   [[ $line =~ ^Size:\s+(\S+) ]] && ((kb += ${.sh.match[1]}))
done

print $kb
6 голосов
/ 07 марта 2011

Хороший тест для более «реального» использования - открыть приложение, затем запустить vmstat -s и проверить статистику «активной памяти». Закройте приложение, подождите несколько секунд и снова запустите vmstat -s. Как бы много активной памяти не было освобождено, она явно использовалась приложением.

5 голосов
/ 17 июля 2018

Я использую Arch Linux и есть этот замечательный пакет под названием ps_mem

ps_mem -p <pid>

Пример вывода

$ ps_mem -S -p $(pgrep firefox)

Private   +   Shared  =  RAM used   Swap used   Program

355.0 MiB +  38.7 MiB = 393.7 MiB    35.9 MiB   firefox
---------------------------------------------
                        393.7 MiB    35.9 MiB
=============================================
5 голосов
/ 08 мая 2013

Если процесс не использует слишком много памяти (или потому, что вы ожидаете, что это так, или какая-то другая команда дала такое начальное указание), и процесс может выдержать остановку на короткий период времени, можно попробовать использовать команду gcore.

gcore <pid>

Проверьте размер сгенерированного файла ядра, чтобы понять, сколько памяти использует конкретный процесс.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...