Я немного запутался в некоторых результатах, которые я вижупсибесплатно.
На моем сервере это результатfree -m
[root@server ~]# free -m
total used free shared buffers cached
Mem: 2048 2033 14 0 73 1398
-/+ buffers/cache: 561 1486
Swap: 2047 11 2036
Насколько я понимаю, Linux управляет памятью, он будет хранить использование диска в ОЗУ, чтобы каждый последующий доступ был быстрее. Я полагаю, что это указано в столбцах "cached". Кроме того, в ОЗУ хранятся различные буферы, указанные в столбце "buffers".
Итак, если я правильно понимаю, «фактическое» использование должно быть «использованным» значением «-/+ буферов/кэша», или 561 в данном случае.
Итак, если предположить, что все это верно, то меня сбивают с толку результаты ps aux
.
Насколько я понимаю результаты ps
, шестой столбец (RSS) представляет собой размер памяти в килобайтах, который процесс использует.
Итак, когда я запускаю эту команду:
[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52
Разве результатом не должен быть столбец «использовано» из «-/+ буферов/кэша» free -m
?
Итак, как мне правильно определить использование памяти процессом в Linux? Видимо, моя логика ошибочна.
решение1
Бесстыдно копирую/вставляю свой ответ изошибка серверабуквально на днях :-)
Система виртуальной памяти Linux не так проста. Вы не можете просто сложить все поля RSS и получить значение, сообщаемое used
. free
Для этого есть много причин, но я назову несколько самых важных.
Когда процесс разветвляется, и родительский, и дочерний процессы будут отображаться с одинаковым RSS. Однако Linux использует копирование при записи, так что оба процесса на самом деле используют одну и ту же память. Только когда один из процессов изменяет память, она фактически дублируется.
Это приведет к тому,free
что число будет меньшеtop
суммы RSS.Значение RSS не включает разделяемую память. Поскольку разделяемая память не принадлежит ни одному процессу,
top
не включает ее в RSS.
Это приведет к тому,free
что число будет большеtop
суммы RSS.
Есть много других причин, по которым цифры могут не сходиться. Этот ответ просто пытается показать, что управление памятью очень сложно, и вы не можете просто сложить/вычесть отдельные значения, чтобы получить общее использование памяти.
решение2
Если вы ищете цифры памяти, которые суммируются, посмотритесмэм:
smem — это инструмент, который может предоставить многочисленные отчеты об использовании памяти в системах Linux. В отличие от существующих инструментов, smem может предоставить отчет о пропорциональном размере набора (PSS), который является более значимым представлением объема памяти, используемой библиотеками и приложениями в системе виртуальной памяти.
Поскольку большие части физической памяти обычно совместно используются несколькими приложениями, стандартная мера использования памяти, известная как размер резидентного набора (RSS), значительно переоценивает использование памяти. Вместо этого PSS измеряет «справедливую долю» каждого приложения в каждой общей области, чтобы дать реалистичное измерение.
Например, здесь:
# smem -t
PID User Command Swap USS PSS RSS
...
10593 root /usr/lib/chromium-browser/c 0 22868 26439 49364
11500 root /usr/lib/chromium-browser/c 0 22612 26486 49732
10474 browser /usr/lib/chromium-browser/c 0 39232 43806 61560
7777 user /usr/lib/thunderbird/thunde 0 89652 91118 102756
-------------------------------------------------------------------------------
118 4 40364 594228 653873 1153092
Так PSS
что интересный столбец здесь, потому что он учитывает общую память.
В отличие от RSS
него имеет смысл суммировать его. Мы получаем 654 Мб всего для процессов пользовательского пространства здесь.
Общесистемный вывод расскажет об остальном:
# smem -tw
Area Used Cache Noncache
firmware/hardware 0 0 0
kernel image 0 0 0
kernel dynamic memory 345784 297092 48692
userspace memory 654056 181076 472980
free memory 15828 15828 0
----------------------------------------------------------
1015668 493996 521672
Итак, 1 ГБ оперативной памяти в целом = 654 МБ пользовательских процессов + 346 МБ памяти ядра + 16 МБ свободной
(с погрешностью в несколько МБ)
В целом около половины памяти используется для кэширования (494 Мб).
Бонусный вопрос: что такое кэш пользователя и кэш ядра?
кстати, для наглядности попробуйте:
# smem --pie=name
решение3
Действительно хороший инструмент — это pmap
список текущего использования памяти для определенного процесса:
pmap -d PID
Для получения более подробной информации см. страницу руководства man pmap
, а также взгляните на20 инструментов мониторинга системы Linux, которые должен знать каждый системный администратор, в котором перечислены замечательные инструменты, которые я всегда использую для получения информации о моем компьютере с Linux.
решение4
Как правильно отметили другие, трудно получить представление о фактическом объеме памяти, используемой процессом, учитывая общие регионы, файлы mmap и прочее.
Если вы экспериментатор, вы можете запуститьvalgrind и массив. Это может быть немного тяжело для обычного пользователя, но вы получите представление о поведении памяти приложения с течением времени. Если malloc() приложения — это именно то, что ему нужно, то это даст вам хорошее представление о реальном использовании динамической памяти процессом. Но этот эксперимент может быть «отравлен».
Чтобы усложнить ситуацию, Linux позволяет вампереобязательствовашу память. Когда вы делаете malloc() памяти, вы заявляете о своем намерении использовать память. Но выделение на самом деле не происходит, пока вы не запишете байт в новую страницу вашей выделенной "RAM". Вы можете убедиться в этом сами, написав и запустив небольшую программу на C, например:
// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
void *p;
sleep(5)
p = malloc(16ULL*1024*1024*1024);
printf("p = %p\n", p);
sleep(30);
return 0;
}
# Shell:
cc test.c -o test && ./test &
top -p $!
Запустите это на компьютере с объемом оперативной памяти менее 16 ГБ, и, вуаля!, вы только что получили 16 ГБ памяти! (нет, на самом деле нет).
Обратите внимание, что top
вы видите «VIRT» как 16.004G, но %MEM равен 0.0
Запустите это еще раз с помощью valgrind:
# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30
А massif говорит "sum of all allocs() = 16GB". Так что это не очень интересно.
НО, если вы запустите его нав своем умепроцесс:
# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30
--------------------------------------------------------------------------------
Command: cc test.c -o test
Massif arguments: (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------
KB
77.33^ :
| #:
| :@::@:#:
| :::::@@::@:#:
| @:: :::@@::@:#:
| ::::@:: :::@@::@:#:
| ::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
| :@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
0 +----------------------------------------------------------------------->Mi
0 1.140
И здесь мы видим (очень эмпирически и с очень высокой степенью уверенности), что компилятор выделил 77 КБ кучи.
Зачем так стараться получить только использование кучи? Потому что все общие объекты и текстовые разделы, которые использует процесс (в этом примере компилятор), не очень интересны. Они являются постоянными накладными расходами для процесса. Фактически, последующие вызовы процесса почти "бесплатны".
Также сравните и сопоставьте следующее:
MMAP() файл размером 1 ГБ. Ваш VMSize будет 1+ ГБ. Но ваш Resident Set Size будет только теми частями файла, которые вы вызвали для подкачки (путем разыменования указателя на эту область). И если вы «прочитаете» весь файл, то к тому времени, как вы дойдете до конца, ядро может уже выгрузить начало (это легко сделать, потому что ядро точно знает, как/где заменить эти страницы при повторном разыменовании). В любом случае, ни VMSize, ни RSS не являются хорошими индикаторами «использования» вашей памяти. На самом деле вы ничего не выделили с помощью malloc().
Напротив, Malloc() и затрагивают МНОГО памяти — пока ваша память не будет выгружена на диск. Так что ваша выделенная память теперь превышает ваш RSS. Здесь ваш VMSize может начать вам что-то говорить (ваш процесс владеет большим объемом памяти, чем то, что фактически находится в вашей RAM). Но все еще сложно отличить VM, которая является общими страницами, от VM, которая является выгруженными данными.
Вот тут valgrind/massif становится интересным. Он показывает вам, что вынамеренновыделено (независимо от состояния ваших страниц).