Ответ 1
В OSX монитор активности дает вам действительно хорошее предположение.
Частная память - это память, которая используется только вашим приложением. Например. стек памяти и вся память, динамически зарезервированная с использованием malloc() и сопоставимых функций/методов (метод alloc для Objective-C) - это частная память. Если вы используете fork, частная память будет делиться с вами дочерним, но будет отмечена копией на запись. Это означает, что до тех пор, пока страница не будет изменена ни процессом (родителем, ни ребенком), она будет разделяться между ними. Как только любой процесс изменяет любую страницу, эта страница копируется до ее изменения. Даже если эта память разделяется с дочерними элементами fork (и она может только делиться с детьми fork), она по-прежнему отображается как память "private", потому что в худшем случае каждая ее страница будет получать изменен (рано или поздно), а затем снова будет закрыт для каждого процесса.
Общая память - это либо память, которая в настоящее время используется совместно (одни и те же страницы видны в виртуальном пространстве процессов различных процессов), либо, вероятно, станут доступными в будущем (например, постоянная память, поскольку нет оснований для не разделяя память только для чтения). По крайней мере, как я прочитал исходный код некоторых инструментов командной строки от Apple. Поэтому, если вы обмениваетесь памятью между процессами с помощью mmap (или сопоставимого вызова, который отображает одну и ту же память в несколько процессов), это будет разделяемая память. Однако сам исполняемый код также является разделяемой памятью, так как если запускается другой экземпляр вашего приложения, нет причин, по которым он может не использовать уже загруженный в память код (исполняемые кодовые страницы по умолчанию доступны только для чтения, если только вы не используете свой приложение в отладчике). Таким образом, разделяемая память - это действительно память, используемая вашим приложением, так же как и частная, но она может быть дополнительно передана другому процессу (или, возможно, нет, но почему он не учитывает ваше приложение, если оно было общим?)
Реальная память - это объем оперативной памяти, который в настоящее время "назначен" вашему процессу, независимо от того, является ли он приватным или общим. Это может быть точно сумма частных и общих, но обычно это не так. У вашего процесса может быть больше памяти, назначенной ему, чем требуется в настоящее время (это ускоряет запросы на большее количество памяти в будущем), но это не является потерей для системы. Если другой процесс требует памяти и свободной памяти нет, до того, как система начнет замену, она отвлечет эту дополнительную память от вашего процесса и назначит ей другой процесс (который является быстрой и безболезненной операцией); поэтому ваш следующий вызов malloc может быть несколько медленнее. Реальная память также может быть меньше частной и физической памяти; это потому, что если ваш процесс запрашивает память из системы, он получит только "виртуальную память". Эта виртуальная память не связана с какими-либо реальными страницами памяти, если вы ее не используете (поэтому malloc 10 МБ памяти использует только один байт, ваш процесс получит только одну страницу, 4096 байт, выделенной памяти - остальное назначается только в том случае, если вы действительно когда-либо нуждаетесь в этом). Дальнейшая память, которая обменивается, может также не учитываться в реальной памяти (не уверен в этом), но она будет учитываться в общей и частной памяти.
Виртуальная память - это сумма всех блоков адресов, которые считаются действительными в пространстве приложений. Эти адреса могут быть связаны с физической памятью (то есть снова частной или общей), или они могут не быть, но в этом случае они будут связаны с физической памятью, как только вы используете адрес. Доступ к адресам памяти за пределами известных адресов приведет к сбою SIGBUS и вашего приложения. Когда память заменяется, виртуальное адресное пространство для этой памяти остается в силе, и доступ к этим адресам заставляет память обмениваться обратно.
Вывод:
Если ваше приложение явно или неявно использует разделяемую память, частная память - это объем памяти, который требуется вашему приложению из-за размера стека (или размеров при многопоточности) и из-за вызовов malloc(), которые вы сделали для динамической памяти. В этом случае вам не нужно много заботиться о совместной или реальной памяти.
Если ваше приложение использует общую память, и это включает в себя графический интерфейс пользователя, где память используется совместно с вашим приложением и WindowServer, например, вы можете также взглянуть на общую память. Очень высокий номер общей памяти может означать, что на данный момент у вас слишком много графических ресурсов, загруженных в память.
Реальная память мало интересна для разработки приложений. Если он больше, чем сумма общих и частных, то это означает ничего, кроме того, что система ленив в памяти за пределами вашего процесса. Если он меньше, тогда ваш процесс запросил больше памяти, чем это было на самом деле, что тоже неплохо, так как, пока вы не используете всю запрошенную память, вы не "крадете" память из системы. Если он намного меньше, чем сумма общих и частных, вы можете рассмотреть возможность запрашивать меньше памяти, если это возможно, поскольку вы немного перегружаете память (опять же, это неплохо, но это говорит мне, что ваш код не является оптимизированный для минимального использования памяти, и если он является кросс-платформой, на других платформах может не быть такой сложной обработки памяти, поэтому вы можете предпочесть выделить много маленьких блоков, а не несколько больших, например, или освободить память намного раньше, и поэтому далее).
Если вы все еще не довольны всей этой информацией, вы можете получить еще больше информации. Откройте терминал и запустите:
sudo vmmap <pid>
где находится идентификатор процесса вашего процесса. Это покажет вам статистику для блока КАЖДЫЙ в вашем пространстве процесса с начальным и конечным адресом. Он также расскажет вам, откуда взялась эта память (сопоставленный файл "Память стека": память Malloc'а - раздел __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% памяти было выгружено на диск)