2009-12-11 7 views
4

Я пытаюсь измерить использование памяти процесса (ява программы) на Linux и есть два вопроса, связанные с что:Измерение использования памяти процесса на Linux

  1. Я попытался с помощью сценария ps_mem.py (сумма значений из/proc/$ PID/smaps), а пик общего использования памяти - около 135 МБ (частная и разделяемая память). Объем общей памяти меньше 1 МБ. Попытка использовать Valgrind с массивом valgrind --tool=massif --trace-children=yes --stacks=yes java myProgram дает около 10 МБ в пике использования памяти.
    Теперь, насколько я понимаю, куча - это где хранятся переменные моей программы, означает ли это, что разница между этими двумя методами - это пространство, занимаемое самим кодом (включая jvm)?

  2. Одинаковая программа использует различный объем памяти на разных компьютерах, если у них разный объем ОЗУ или/и использование разных процессоров (ARM или x86)?

ответ

3
  1. Зависит.
    • Многие сопоставления с общей памятью в smaps непосредственно поддерживаются библиотеками/двоичными файлами на диске. В то время как след этих аспектов имеет значение, это менее важно, поскольку система может удалить эти страницы в любое время и перезагрузить их с диска, когда это необходимо снова.
    • Все, что является грязным или закрытым, принадлежит исключительно текущему процессу (ну, дерево процессов, если ваша программа вилки без execs). Это более важно, потому что система должна сохранять их для свопинга, если им нужно вывести эти страницы из памяти.
    • Какой массив измеряет, вероятно, коррелирует с последним. Однако память, взятая самим JVM (без вашей программы), находится в обоих.
  2. Да. Java или используемая им библиотека могут настроить свою модель памяти в зависимости от размера доступной ОЗУ.В другой архитектуре вы используете совершенно разные бинарные файлы, которые могут быть больше или меньше или расположены по-разному или с использованием разных стратегий для JIT и управления памятью.
1

Для # 1 общая память - это память (потенциально), используемая более чем одним процессом. Это в основном, если вы запускаете один и тот же двоичный файл в нескольких процессах или разные процессы используют общую библиотеку. Куча - это место хранения выделенной памяти (когда вы используете new в Java). Поскольку Java имеет свою виртуальную машину, она выделяет много памяти на уровне процесса, который вы не видите в своем Java-коде. Я думаю, что да, большинство из этих 135 МБ - из кода JVM/данных. Тем не менее, есть также память, занятая стекем (когда вы делаете вызов функции и имеете локальные переменные).

Для # 2 разное количество ОЗУ не повлияет на то, сколько «памяти» используется, когда мы позволяем памяти равным ОЗУ + место подкачки. Однако разные процессоры (особенно, если говорить о 32-битных и 64-битных) могут использовать разный объем памяти. Кроме того, способ компиляции процесса может изменить объем используемой памяти, поскольку вы можете дать команду компилятору оптимизировать размер памяти по скорости, а также полностью отключить некоторую или всю оптимизацию.

0

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

Что касается массива, вы должны знать, что части JVM будут храниться в стеке, а сам код java может находиться в куче (поскольку это переменная JVM), я не знаю достаточно о JVM сказать.

3

Существует аналогичный вопрос, отличный от этого, и отвечая на то же самое здесь, чтобы люди знали о том, как в настоящее время информация о статусе linux proc stat vm неточна.
Valgrind может отображать подробную информацию, но значительно замедляет целевое приложение и большую часть времени изменяет поведение приложения.

Я предполагаю, что все хотят знать, что использование памяти «WRT» является следующим ...
В linux количество физической памяти, которую может использовать один процесс, можно условно разделить на следующие категории.

  • Ма анонимным сопоставляются памяти
    • .p частный
      • .d грязного == таНос/mmapped кучи и стека выделяется и написано модуля памяти
      • .c чистый == таНос/mmapped кучу и стоп-память, выделенная, написанная, затем освобожденная, но не исправленная
    • .s shared
      • .d загрязнен == не должно быть ни
      • .c чистый == не должно быть ни
  • Mn назвал карту памяти
    • .p частный
      • .d грязный == файл mmapped запись приватная
      • .c чистый == отображается текст программы/библиотеки частным сопоставляются
    • .са совместно
      • .d грязного файл == mmapped написал память совместно
      • .c чистого == сопоставляется библиотека текст поделилась сопоставляется

Я бы предпочел, чтобы получить числа следующим образом, чтобы получить действительные числа в наименее Ове rhead.
Вы должны суммировать их, чтобы разделить то, что показывает ps как RSS, и получать более точные цифры, чтобы не путать.
/proc/(pid)/status пытается показать эти цифры, но они не работают.
Таким образом, вместо того, чтобы пытаться помечать [anon], [stack], правильно для каждого сопоставления, мое желание , что люди ядра Linux будут использовать код ввода proc для суммирования и отображения этих Mapd, Mapc, Mnpd, .... номера.
Встраиваемые Linux-пользователи получат действительно счастливое ИМХО.

M.a.p.d:

awk '/^[0-9a-f]/{if ($6=="") {anon=1}else{anon=0}} /Private_Dirty/{if(anon) {asum+=$2}else{nasum+=$2}} END{printf "sum=%d\n",asum}' /proc/<pid>/smaps 

M.a.p.c:

awk '/^[0-9a-f]/{if ($6=="") {anon=1}else{anon=0}} /Private_Clean/{if(anon) {asum+=$2}else{nasum+=$2}} END{printf "sum=%d\n",asum}' /proc/<pid>/smaps 

M.n.p.d: ... и так далее