На OSX Activity Monitor дает очень хорошие предположения.
Частная память - это, несомненно, память, используемая только вашим приложением. Например. стековая память и вся память, динамически зарезервированная с использованием malloc () и сопоставимых функций / методов (метод alloc для Objective-C), является частной памятью. Если вы разветвляетесь, ваша личная память будет разделена с вашим ребенком, но помечена как копируемая при записи. Это означает, что до тех пор, пока страница не изменяется ни одним процессом (родительским или дочерним), она разделяется между ними. Как только любой процесс изменяет какую-либо страницу, эта страница копируется перед изменением. Даже если эта память используется совместно с дочерними вилками (и она может быть только доступной для дочерних вилок), она все равно отображается как «частная» память, потому что в худшем случае каждая ее страница будет изменена (рано или поздно), а затем он снова становится приватным для каждого процесса.
Совместно используемая память - это либо память, которая в данный момент используется совместно (одни и те же страницы видны в пространстве виртуальных процессов разных процессов), либо она может стать общей в будущем (например, постоянная память, поскольку нет причин для не разделяет постоянную память). По крайней мере, так я прочитал исходный код некоторых инструментов командной строки от Apple. Так что если вы разделяете память между процессами, используя mmap (или сопоставимый вызов, который отображает одну и ту же память на несколько процессов), это будет общая память. Однако сам исполняемый код также является разделяемой памятью, поскольку при запуске другого экземпляра вашего приложения нет никаких причин, по которым он может не делиться кодом, уже загруженным в память (по умолчанию исполняемые кодовые страницы доступны только для чтения, если вы не запускаете приложение в отладчике). Таким образом, разделяемая память на самом деле является памятью, используемой вашим приложением, точно так же, как и частная, но она может дополнительно использоваться совместно с другим процессом (или не может, но почему она не будет учитываться в вашем приложении, если оно было общим?)
Реальная память - это объем оперативной памяти, в настоящее время «назначенный» вашему процессу, независимо от того, является ли он частным или общим. Это может быть как раз сумма частного и общего, но обычно это не так. Вашему процессу может быть выделено больше памяти, чем ему требуется в настоящее время (это ускоряет запросы на увеличение памяти в будущем), но это не потеря для системы. Если другому процессу требуется память и свободной памяти нет, то до того, как система начнет замену, она заберет эту дополнительную память у вашего процесса и назначит другой процесс (что является быстрой и безболезненной операцией); поэтому ваш следующий вызов 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% памяти было выгружено на диск)