Я использую VMMap для анализа использования виртуального / адресного пространства процесса в моем приложении смешанного режима (управляемого и неуправляемого). Я понимаю, как работает Windows VMM и API виртуальной памяти, я понимаю, как работает API Heap Memory. Я посмотрел на реализацию CRT, которую я использую (не очень подробно), и (думаю, я — это может быть моим упадком), чтобы понять, как она использует вышеупомянутые Win32 API.
Я пытаюсь понять, что показывает эта статистика «Личные данные». Мое приложение не обращается напрямую ни к одной из функций API памяти Win32, оно всегда использует «malloc / new» в нативном C ++ и «new» в C # (в глубине души будет использоваться Win32 API управления памятью).
Определение «Частные данные», данное VMMap:
Частная память — это память, выделенная VirtualAlloc, а не
выделяется либо в диспетчере кучи, либо во время выполнения .NET. Это
не может использоваться совместно с другими процессами, взимается с системы
предел фиксации, и обычно содержит данные приложения.
Итак, я думаю, это определение заставляет меня спросить, хорошо, так кто же звонит в VirtualAlloc? Это менеджер кучи или .Net время выполнения?
Я мог бы получить адрес некоторых конфиденциальных данных и использовать WinDbg, чтобы выяснить …. Ну … получается, что Microsoft в своей мудрости добавила публичные символы ntdll, так что WinDbg не работает так хорошо — я может предоставить более подробную информацию об этом, если требуется, но в основном такие команды, как! address -summary, больше не работают из-за пропущенных символов.
Другой способ сформулировать этот вопрос: какой код C ++ или C # можно написать, что приведет к увеличению или уменьшению статистики личных данных? Или все это управляется ОС, средой выполнения C ++ или средой .Net и, следовательно, зависит от ее прихотей?
Я могу сделать вывод из природы VMMap (другие типы памяти являются ИСКЛЮЧИТЕЛЬНЫМИ КАЖДОГО ДРУГОГО), что эти «личные данные», следовательно, не могут быть следующими типами адресного пространства:
(Я не смог найти файл интерактивной справки, который определяет, что VMMap считает всеми перечисленными выше типами, но вот ссылка для скачивания файла справки: https://technet.microsoft.com/en-us/library/dd535533.aspx)
Я заметил, что в моем приложении ОБЩИЙ (зарезервированный и фиксированный) размер личных данных остается довольно постоянным на протяжении всего срока службы моих приложений, несмотря на то, что размеры кучи / управляемой кучи / стека изменяются, как и ожидалось. Я также заметил, что из общего объема ~ 250 МБ, используемого частными данными, фактически выделяется только ~ 33 МБ. Обратите внимание, что мой метод измерения это довольно элементарный, поэтому значение может меняться между каждым из моих измерений, и я просто не вижу его (если бы я знал, что это измеряется, я мог бы использовать DebugDiag, чтобы получить дамп процесса, когда соответствующий счетчик достиг определенного порога (курица и яйцо).
Моя текущая спекулятивная теория состоит в том, что это пространство, которое резервируется для роста собственных (или, я полагаю, управляемых) кучи, когда они достигают своих возможностей, но у меня нет ничего, чтобы доказать это. Так что он твердо остается в спекулятивной куче.
Поиск в Интернете подробностей об этом может быть болезненным, есть много публикаций / статей / блогов, которые путают вещи, используют самостоятельные ссылочные определения (первое предложение определения Performance Monitor для рабочего набора является отличным примером этого), неполные или просто неправильно. Во многих местах размыты определения или используется противоречивая терминология (обратите внимание, что определение VMMaps поля приватных данных продолжает называть его приватной памятью, возможно, немного анальной жалобой, но неоднозначностью).
Теперь, когда я раскритиковал остальную часть интернета за то, что все запутано и некорректно … если в вышеприведенном есть что-то, что не имеет смысла, или вы можете показать мне документацию об обратном, или вам нужно более четкое определение , дайте мне знать, и я тоже внесу себя в список правонарушителей! Я думаю, что первая половина попытки объяснить кому-то проблему с памятью в Интернете — убедиться, что мы все говорим об одном и том же.
Напоследок этот вопрос: Откуда VMMap знает, что конкретная область памяти является стеком потоков, в частности? предполагает, что я никогда не узнаю ответ: /
ОБНОВЛЕНИЕ / РЕДАКТИРОВАНИЕ: я обнаружил, что, включив трассировку стека пользователей gflags (gflags -i myapp.exe + ust), вы можете увеличить размер личных данных, я бы предположил, что это база данных с обратным следом, но там даже без gflags Есть еще частные данные, которые я изо всех сил пытаюсь объяснить.
Я знаю, что это довольно старый вопрос. Но это по-прежнему без ответа по какой-то причине. Этот вопрос упоминал Саша Гольдштейн в своем выступлении о WinDbg на конференции DotNext — https://www.youtube.com/watch?v=8t1aTbnZ2CE.
Дело в том, что на него легко ответить с помощью WinDbg.
Чтобы ответить, использует ли CLR VirtualAlloc для своей кучи, мы установим точку останова для этой функции с помощью сценария, который печатает текущий стек (собственный и управляемый).
bp kernelbase!VirtualAlloc ".printf \"allocating %d bytes of virtual memory\", dwo(@esp+8);.echo; k 5; !clrstack; gc"
Вот: k 5
напечатать последние 5 кадров нативного стека вызовов и !clrstack
(из SOS) печатает управляемый стек. gc
продолжить исполнение.
Обратите внимание, что этот скрипт будет работать только для процессов x86. Для x64 вам понадобятся другие (реестры и соглашение о вызовах различаются).
Затем я создал простую программу, которая выделяет объект и добавляет его в список.
static void Main(string[] args)
{
var list = new List<string[]>();
while (true) {
var a = Console.ReadLine();
if (a == "q" || a == "Q") break;
var arr = new string[100];
list.Add(arr);
}
}
Запустите его под WinDbg и начните нажимать Enter. В какой-то момент точка останова попала в список, расширяющийся и выделяющий дополнительную память в куче:
Очевидно, что CLR использует VirtualAlloc для выделения памяти для своей кучи.
Других решений пока нет …