Что такое частные байты, виртуальные байты, рабочий набор?

491

Я пытаюсь использовать утилиту perfmon для отладки утечек памяти в процессе.

Вот как perfmon объясняет термины:

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

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

Частные байты - это текущий объем памяти в байтах, выделенный этим процессом, который нельзя использовать совместно с другими процессами.

Вот вопросы, которые у меня есть:

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

Какова общая память, используемая процессом? Это виртуальные байты или сумма виртуальных байтов и рабочего набора?

Есть ли какая-либо связь между частными байтами, рабочим набором и виртуальными байтами?

Есть ли другие инструменты, которые дают лучшее представление об использовании памяти?

pankajt
источник
3
Лучшим инструментом будет valgrind / helgrind, но, к сожалению, не под Windows :(
Kornel Kisielewicz
Должен ли я измерить частный байт, чтобы убедиться, что у процесса есть утечка? Если личные байты процесса не растут, у вас нет утечек памяти. Если они растут, это может быть связано с утечками памяти, и это может быть связано с фрагментацией памяти. Я думаю, что, глядя на рост частных байтов, трудно сказать, что именно это означает.
@SergeiKurenkov Одно можно сказать, что это НИКОГДА не будет связано с «фрагментацией памяти».
Джейми Ханрахан

Ответы:

517

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

Частные байты относятся к объему памяти, запрошенному исполняемым файлом процесса - не обязательно к объему, который он фактически использует . Они являются «частными», потому что они (обычно) исключают файлы, отображаемые в памяти (то есть разделяемые библиотеки DLL). Но - вот в чем загвоздка - они не обязательно исключают память, выделенную этими файлами . Невозможно определить, произошло ли изменение в частных байтах из-за самого исполняемого файла или из-за связанной библиотеки. Частные байты также не являются исключительно физической памятью; они могут быть перенесены на диск или в список резервных страниц (т.е. больше не используются, но еще не выгружены).

Рабочий набор относится к общей физической памяти (ОЗУ), используемой процессом. Однако, в отличие от частных байтов, это также включает в себя отображенные в память файлы и различные другие ресурсы, поэтому это даже менее точное измерение, чем частные байты. Это то же значение, о котором сообщается в «Использование памяти» диспетчера задач, и в последние годы оно вызывает бесконечную путаницу. Память в рабочем наборе является «физической» в том смысле, что к ней можно обращаться без ошибок страницы; однако, список резервных страниц также все еще физически находится в памяти, но не отображается в рабочем наборе, и поэтому вы можете внезапно сбросить «Использование памяти» при сворачивании приложения.

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

Итак, отношения:

  • Частные байты - это то, что ваше приложение фактически выделило, но включает использование файла подкачки;
  • Рабочий набор - это не страничные частные байты плюс отображенные в памяти файлы;
  • Виртуальные байты - это рабочий набор, постраничные приватные байты и резервный список.

Здесь есть другая проблема; Точно так же, как разделяемые библиотеки могут выделять память внутри модуля приложения, что приводит к потенциальным ложным срабатываниям, сообщаемым в личных байтах вашего приложения , так и ваше приложение может в конечном итоге выделять память внутри общих модулей, что приводит к ложным отрицаниям . Это означает, что на самом деле ваше приложение может иметь утечку памяти, которая вообще никогда не проявляется в приватных байтах. Вряд ли, но возможно.

Частные байты являются разумным приближением к объему памяти, используемому вашим исполняемым файлом, и могут использоваться, чтобы помочь сузить список потенциальных кандидатов на утечку памяти; если вы видите, что число постоянно растет и бесконечно растет, вам следует проверить этот процесс на наличие утечек. Это, однако, не может доказать, что есть или нет утечка.

Одним из наиболее эффективных инструментов для обнаружения / исправления утечек памяти в Windows на самом деле является Visual Studio (ссылка ведет на страницу об использовании VS для утечек памяти, а не на страницу продукта). Rational Purify - это еще одна возможность. У Microsoft также есть более общий документ с рекомендациями по этому вопросу. В этом предыдущем вопросе перечислены другие инструменты .

Я надеюсь, что это проясняет некоторые вещи! Отслеживание утечек памяти - одна из самых сложных вещей при отладке. Удачи.

Aaronaught
источник
26
Боюсь, что вы ответите не совсем правильно. Частные байты относятся к объему памяти (ОЗУ), который запрашивал исполняемый файл процесса, а не только к физической памяти. Таким образом, вы наверняка можете проверить большинство случаев утечки памяти, отслеживая частные байты. Попробуйте :: VisualAlloc, чтобы зафиксировать большой кусок памяти (скажем, 1,5 ГБ). Вы должны увидеть, что ваши личные байты намного больше, чем рабочий набор. Что доказывает, что ваш «Рабочий набор - это частные байты плюс файлы с отображением в памяти» неверен.
Джей Чжу
4
На самом деле, я полагаю, что понимание записи таково: «Рабочий набор - это частные байты в памяти плюс файлы, отображаемые в память». А приватные байты МОГУТ быть заменены - вы можете видеть приватные байты больше, чем физическая память у вас в машине.
Джей Чжу
2
@Aaronaught: Ваше первое утверждение о надежном индикаторе и подходящем для отладки сбивает с толку. Приватные байты являются надежным индикатором утечки памяти приложения. Это может быть зависимая DLL и косвенная, но это утечка в области памяти приложения. Можете ли вы объяснить, почему его нельзя использовать для отладки? полный дамп памяти процесса приложения должен сказать нам, что потребляет эту память. Я не уверен, что понимаю, почему его нельзя использовать для отладки. Можете ли вы пролить свет?
G33kKahuna
@ G33kKahuna: Мне не понятно, как дамп памяти скажет вам, что потребляет память в каком-либо значимом смысле - если только «что» вы не имеете в виду «какие модули», но все, что у вас есть, - это снимок, вы все равно не можете видеть какой модуль на самом деле теряет память со временем, если вы не предпримете несколько дампов со временем и в строго контролируемых условиях. Трудно представить себе более неэффективную и ненадежную стратегию отладки. Профилировщики везде в наши дни; использовать один.
Aaronaught
1
Запустите полный! Objsize, это должно показать все закрепленные объекты в непосредственной куче. Вы можете подтвердить это, проверив eeheap -gc. Это должно показать вам, где объем застрял. Как правило, если никакие подсказки не доступны для всех вышеперечисленных команд, ваши личные байты потребляются несобранными объектами в GC. Теперь перейдите к gchandles или gcleaks. Эти команды должны сказать вам, какие типы / адрес объекта не могут быть отображены. Указатель все еще там, но объект исчез. Это такая категорическая проблема для невыпущенных обработчиков событий.
G33kKahuna
10

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

Предыдущий ответ на этот вопрос дал отличное объяснение того, что представляют собой различные типы.

Вы спрашиваете о рекомендации инструмента: я рекомендую Memory Validator. Возможность мониторинга приложений, которые выделяют миллиарды памяти.

http://www.softwareverify.com/cpp/memory/index.html

Отказ от ответственности: я разработал Memory Validator.

Стивен Келлетт
источник
1
Я не могу даже запустить простой файл класса (на Java)? Что дает?
jn1kk
Я подозреваю, что Стивен и Дьявол как-то связаны или даже клонированы ...: D;)
Роберт Коритник
@StephenKellett, есть пробная версия?
Pacerier
@Pacerier, если вы перейдете по ссылке, будет доступна пробная версия для версий x86 и x64 чуть выше опции покупки в левой части страницы.
Брэдли А. Тетро
10

Определение счетчиков perfmon было нарушено с самого начала и по некоторым причинам кажется слишком сложным для исправления.

Хороший обзор управления памятью Windows доступен в видеоролике « Раскрытые тайны управления памятью » на MSDN: он охватывает больше тем, чем необходимо для отслеживания утечек памяти (например, управление рабочим набором), но дает достаточно деталей в соответствующих темах.


Чтобы дать вам подсказку о проблеме с описаниями счетчика perfmon, вот внутренняя история о частных байтах из « Счетчика производительности частных байтов - Осторожно! » На MSDN:

В: Когда личный байт не является личным?

A: Когда это не резидент.

Счетчик Private Bytes сообщает о фиксации процесса. Другими словами, объем пространства, выделенного в файле подкачки для хранения содержимого приватной памяти в случае ее замены. Примечание: я избегаю слова «зарезервировано» из-за возможной путаницы с виртуальной памятью в зарезервированном состоянии, которая не зафиксирована.


Из « Планирования производительности » на MSDN:

3.3 Частные байты

3.3.1 Описание

Частная память, определяется как память, выделенная для процесса, который не может использоваться другими процессами. Эта память дороже разделяемой памяти, когда на машине выполняется несколько таких процессов. Частная память в (традиционных) неуправляемых dll обычно состоит из статики C ++ и составляет порядка 5% от общего рабочего набора dll.

отметка
источник
1
голосование из-за безумно хороших примеров о том, как это сломалось!
Бруно Брант
Первая цитата ошибочна. Выделение «Частных байтов» не требует, чтобы что-либо было «размещено в файле подкачки» (которое на самом деле называется файлом подкачки). Вам даже не нужно иметь файл подкачки для выделения «приватных байтов». На самом деле, выделяя частные байты не сразу использовать любое пространство где - нибудь , и не может когда - либо использовать столько , сколько было выделено.
Джейми Ханрахан
Вторая цитата не намного лучше. Частные байты, используемые в коде DLL, не обязательно в основном статически размещены в DLL. Код DLL совершенно свободно вызывать VirtualAlloc, HeapAlloc (malloc и new в CRTL) и т. Д. Он также пытается описать размер частной памяти в процентах от размера рабочего набора, что является бессмысленным. Первый - виртуальный размер (и он будет одинаковым для каждого использования кода с одним и тем же вводом), а второй - физический (который может радикально отличаться от одного прогона к другому, в зависимости от того, насколько много памяти или - голодная машина есть).
Джейми Ханрахан
5

Здесь есть интересная дискуссия: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ Я понимаю, что освобождение небольших ресурсов не отражается в частных байтах или рабочем наборе.

Короче говоря:

если я позвоню

p=malloc(1000);
free(p);

тогда частные байты отражают только распределение, а не освобождение.

если я позвоню

p=malloc(>512k);
free(p);

тогда частные байты правильно отражают распределение и освобождение.

mcanti
источник
7
Это объясняется тем фактом, что функции памяти стандартной библиотеки C используют пользовательскую или Win32 Heap, которая является механизмом управления памятью поверх низкоуровневого управления памятью на уровне процесса.
Киберия
@Kyberias, так как же нам стать ниже этого?
Pacerier
в то время как (1) бесплатно (malloc (1000)); // Будет ли это привести к увеличению личных байтов навсегда?
Франкспайк
2
@franckspike: нет, он увеличится до определенной точки (обычно около 4 кБ, но это может варьироваться) и затем остановится, потому что CRT будет повторно использовать ранее освобожденную память вместо запроса новых страниц из ОС.
Мирал
@Pacerier: вы можете позвонить в VirtualAlloc и VirtualFree.
Джейми Ханрахан