.NET API для определения фрагментации виртуальной машины

StackOverflow https://stackoverflow.com/questions/2119117

  •  22-09-2019
  •  | 
  •  

Вопрос

Существует ли .NET API для получения подробной информации об использовании виртуальной машины?Меня особенно интересует определение того, насколько фрагментировано мое адресное пространство.

Спасибо!

Это было полезно?

Решение

Некоторые функции Windows API, которые могут дать вам некоторое представление об этом, — это VirtualQueryEx() для перечисления разделов виртуальной памяти и обнаружения неиспользуемого пространства, GetProcessHeaps() для определения того, какие кучи создаются внутри процесса, и HeapWalk() для обнаружения блоков в используется каждая куча.

Это будет непросто, особенно HeapWalk() — неприятная функция в работающей программе.Вам следует взглянуть на SysInternals. Утилита VMMap, он обеспечивает превосходную диагностику виртуальной памяти.

Недостаток этого подхода в том, что он на самом деле не помогает решить проблему фрагментации памяти.Вы ничего не можете сделать, чтобы повлиять на то, как диспетчер памяти Windows распределяет пространство виртуальной памяти.Коротко из-за не выделения памяти.Если вы сейчас боретесь с OOM, вам действительно следует подумать о перепроектировании вашего приложения.Или переключиться на 64-битную операционную систему — решение за двести долларов.

Другие советы

Короткий ответ:нет.Для этого вам нужно подключиться к Win32 API.Я действительно не знаю, какой вызов API вы бы использовали...

Быстрый поиск по http://www.pinvoke.net привел меня к этому:

[DllImport("coredll.dll", SetLastError=true)]
static extern void GlobalMemoryStatus(ref MEMORYSTATUS lpBuffer);

Но структура MEMORYSTATUS, похоже, не содержит всей необходимой информации (только использование физической и виртуальной памяти и другая информация).

Вам придется покопаться в MSDN, чтобы найти нужный метод.

Такой вызов не имеет смысла в управляемом мире, поскольку разные узлы CLR могут обрабатывать разные вещи (например, обычный узел приложения или SQL Server).И не забывайте, что сборщик мусора может перемещать объекты, поэтому фрагментация на самом деле не является проблемой, поскольку сборщик мусора уплотняет кучу.

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

Вам действительно нужно погрузиться в API Win32/Win64, чтобы получить эту информацию на уровне страницы.Если более подробно, вам нужно знать внутреннюю работу той кучи, на которую вы смотрите, будь то куча C, куча Win32, куча малых объектов CLR или куча больших объектов CLR.

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

Вот статья в блоге, описывающая, что страницы и абзацы являются.

В C вы можете написать что-то вроде этого, чтобы узнать, сколько памяти выделено:

HANDLE heap = GetProcessHeap();
PROCESS_HEAP_ENTRY entry;
memset(&entry, 0, sizeof(entry));
unsigned long size = 0;
while(HeapWalk(heap, &entry)) {
    if(entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) {
        size += entry.cbData;
    }
}

GetProcessHeaps() может потребоваться, если используются другие кучи, и в этом случае вам понадобится второй цикл для прохождения всех куч.Я не знаю, почему их должно быть больше одного.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top