Способ определить “реальное” использование памяти процесса, т.е. частный грязный RSS?

Вот простой способ сделать это:

x=[1,2,20,6,210]
print sorted(set(x))
49
задан warren 26 November 2008 в 17:51
поделиться

3 ответа

На операционной системе OSX монитор активности дает вам очень хорошую догадку.

Частная память - это точно такая же память, которая используется только вашим приложением. Например, стековая память и вся память, динамически резервируемая с помощью malloc() и аналогичных функций/методов (метод выделения для Objective-C), является приватной памятью. Если вы используете fork, то приватная память будет совместно использоваться с дочерней, но помеченной копией на запись. Это означает, что до тех пор, пока страница не будет изменена ни одним из процессов (родительским или дочерним), она будет совместно использоваться ими. Как только один из процессов модифицирует какую-либо страницу, эта страница копируется перед ее модификацией. Даже если эта память совместно используется с дочерними процессами fork (и она может только совместно использоваться с дочерними процессами fork), она всё равно отображается как "приватная" память, потому что в худшем случае каждая страница этой памяти будет изменена (рано или поздно), а затем она снова станет приватной для каждого процесса.

Общая память - это либо память, которая в настоящее время является общей (одни и те же страницы видны в виртуальном пространстве процессов), либо которая, вероятно, станет общей в будущем (например, память, доступная только для чтения, так как нет причин не совместно использовать память, доступную только для чтения). По крайней мере, так я читаю исходный код некоторых инструментов командной строки от Apple. Так что, если бы вы делили память между процессами, использующими mmap (или аналогичный вызов, который отображает одну и ту же память на несколько процессов), то это была бы общая память. Однако сам по себе исполняемый код также является общей памятью, так как если запущен другой экземпляр вашего приложения, то нет причин, по которым он может не поделиться уже загруженным в память кодом (по умолчанию страницы исполняемого кода доступны только для чтения, если только вы не запускаете приложение в отладчике). Таким образом, разделяемая память - это действительно используемая вашим приложением память, точно такая же, как и приватная память, но дополнительно она может быть совместно использована с другим процессом (а может и нет, но почему бы она не засчитывалась вашему приложению, если бы она была совместно использована?)

Реальная память - это объем оперативной памяти, который в настоящее время "назначен" вашему процессу, независимо от того, является ли он приватным или совместно используемым. Это может быть как раз сумма приватной и разделяемой, но обычно это не так. Вашему процессу может быть выделено больше памяти, чем ему необходимо в настоящее время (это ускоряет запросы на большее количество памяти в будущем), но это не является потерей для системы. Если другому процессу нужна память, а свободной памяти нет, то до того, как система начнет производить замену, она отнимет у вашего процесса эту дополнительную память и назначит ему другой процесс (что является быстрой и безболезненной операцией); для вашего следующего вызова malloc может быть несколько медленнее. Реальная память также может быть меньше частной и физической памяти; это происходит потому, что если ваш процесс запросит память у системы, он получит только "виртуальную память". Эта виртуальная память не связана ни с какими реальными страницами памяти, пока Вы ею не пользуетесь (поэтому malloc 10 Мбайт памяти, используйте только один байт, Ваш процесс получит только одну страницу, 4096 байт, назначенной памяти - остальное будет назначено только в том случае, если она Вам действительно когда-нибудь понадобится). Дальнейшая память, которая будет подкачана, тоже может не засчитываться в реальную память (не уверен в этом), но будет засчитываться в общую и приватную.

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

Заключение:
Если ваше приложение явно или неявно не использует разделяемую память, то приватная память - это количество памяти, которое необходимо вашему приложению из-за размера стека (или размера, если он многопоточный) и из-за вызовов malloc(), которые вы сделали для динамической памяти. В этом случае вам не нужно сильно заботиться об общей или реальной памяти.

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

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

Если вы все еще недовольны всей этой информацией, вы можете получить еще больше информации. Откройте терминал и запустите:

sudo vmmap <pid>

где идентификатор процесса. Это покажет вам статистику по блоку памяти EVERY в вашем пространстве процесса с адресом начала и конца. Также будет указано, откуда взялась эта память (mapped file? Память стека? Память Malloc'ed? Раздел __DATA или __TEXT вашего исполняемого файла?), насколько он велик в КБ, права доступа и является ли он приватным, общим или копируемым на запись. Если он отображен из файла, он даже даст вам путь к файлу.

Если вы хотите только "фактическое" использование оперативной памяти, используйте

sudo vmmap -resident <pid>

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

В конце каждого дампа находится также обзорная таблица с суммами различных типов памяти. Эта таблица выглядит так для Firefox прямо сейчас на моей системе:

REGION TYPE             [ VIRTUAL/RESIDENT]
===========             [ =======/========]
ATS (font support)      [   33.8M/   2496K]
CG backing stores       [   5588K/   5460K]
CG image                [     20K/     20K]
CG raster data          [    576K/    576K]
CG shared images        [   2572K/   2404K]
Carbon                  [   1516K/   1516K]
CoreGraphics            [      8K/      8K]
IOKit                   [  256.0M/      0K]
MALLOC                  [  256.9M/  247.2M]
Memory tag=240          [      4K/      4K]
Memory tag=242          [     12K/     12K]
Memory tag=243          [      8K/      8K]
Memory tag=249          [    156K/     76K]
STACK GUARD             [  101.2M/   9908K]
Stack                   [   14.0M/    248K]
VM_ALLOCATE             [   25.9M/   25.6M]
__DATA                  [   6752K/   3808K]
__DATA/__OBJC           [     28K/     28K]
__IMAGE                 [   1240K/    112K]
__IMPORT                [    104K/    104K]
__LINKEDIT              [   30.7M/   3184K]
__OBJC                  [   1388K/   1336K]
__OBJC/__DATA           [     72K/     72K]
__PAGEZERO              [      4K/      0K]
__TEXT                  [  108.6M/   63.5M]
__UNICODE               [    536K/    512K]
mapped file             [  118.8M/   50.8M]
shared memory           [    300K/    276K]
shared pmap             [   6396K/   3120K]

О чем это говорит нам? Например, бинарный файл Firefox и все загружаемые им библиотеки содержат 108 МБ данных вместе в своих разделах __TEXT, но в настоящее время только 63 МБ из них являются резидентными в памяти. Поддержка шрифтов (ATS) требует 33 Мб, но только около 2.5 Мб действительно находятся в памяти. Она использует чуть более 5 МБ CG-бэкэкапов, CG = Core Graphics, это, скорее всего, содержимое окна, кнопки, изображения и другие данные, которые кэшируются для быстрого рисования. Он запросил 256 Мб с помощью вызовов malloc, и в настоящее время 247 Мб действительно отображаются на страницы памяти. Она имеет 14 МБ пространства, зарезервированного для стеков, но только 248 КБ стека действительно используется в настоящее время.

vmmap также имеет хорошую сводку над таблицей

ReadOnly portion of Libraries: Total=139.3M resident=66.6M(48%) swapped_out_or_unallocated=72.7M(52%)
Writable regions: Total=595.4M written=201.8M(34%) resident=283.1M(48%) swapped_out=0K(0%) unallocated=312.3M(52%)

И это показывает интересный аспект OS X: Для читаемой только памяти она не играет никакой роли, если ее поменять местами или просто не распределить; есть только резидент и не резидент. Для записываемой памяти это имеет значение (в моем случае 52% всей запрашиваемой памяти никогда не использовалось и является такой нераспределенной, 0% памяти было подкачано на диск)

.
44
ответ дан 7 November 2019 в 11:46
поделиться

Top знает, как сделать это. Это показывает VIRT, RES и SHR по умолчанию на Linux Debian. VIRT = ПОДКАЧИВАЮТ + RES. RES = КОДИРУЮТ + ДАННЫЕ. SHR является памятью, которая может быть совместно использована с другим процессом (совместно использованная библиотека или другая память.)

кроме того, 'грязная' память является просто памятью RES, которая использовалась и/или не была подкачана.

может быть трудно сказать, но лучший способ понять состоит в том, чтобы посмотреть на систему, которая не подкачивает. Затем RES - SHR является процессом эксклюзивная память. Однако это не хороший способ посмотреть на него, потому что Вы не знаете, что память в SHR используется другим процессом. Это может представить незаписанные страницы общего объекта, которые только используются процессом.

7
ответ дан Chris 7 November 2019 в 21:46
поделиться

Вы действительно не можете.

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

Меня, я доволен RSS. И знание Вас не может действительно полагаться на него полностью...

6
ответ дан alex 7 November 2019 в 21:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: