Текущее использование памяти всегда на ~ 14 МБ больше, чем в диспетчере задач

В настоящее время я использую код в этот ответ, с некоторыми небольшими изменениями, как предлагается в комментариях. Однако независимо от того, сколько объектов я выделяю в памяти, указанное использование памяти всегда на ~ 14 МБ больше, чем перечисляет диспетчер задач. Почему это может быть?

std::stringstream ss;

PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
SIZE_T physMemUsedByMe = pmc.WorkingSetSize;

ss << "\nMEM: " << (physMemUsedByMe / 1024 / 1024) << " MB";

debugText.setString(ss.str());

Результаты нормальной сборки:

debugText:

debugText

Диспетчер задач:

Диспетчер задач:

Монитор ресурсов:

Монитор ресурсов

Результаты при размещении 10 000 фиктивных объектов:

debugText:

debugText

Диспетчер задач:

Диспетчер задач

Монитор ресурсов:

Монитор ресурсов

РЕДАКТИРОВАТЬ:

После использования Resource Monitor (perfmon) в качестве комментариев, я обнаружил, что столбец для Working Set соответствует функции листинга памяти, которую я использую. Тем не менее, я все еще озадачен тем, почему есть разница ~ 14 МБ между Working Set столбец и Private столбец (последний из которых, по-видимому, используется диспетчером задач). Почему это так?

0

Решение

Диспетчер задач не использует Win32 API GetProcessMemoryInfo() функция. Использует NT API ZwQueryInformationProcess() функция, настройка ProcessInformationClass параметр для ProcessVmCounters,

Начиная с Windows 10, определяется следующая структура (в ntddk.h):

typedef struct _VM_COUNTERS_EX2 {
VM_COUNTERS_EX CountersEx;
SIZE_T PrivateWorkingSetSize;
ULONGLONG SharedCommitUsage;
} VM_COUNTERS_EX2, *PVM_COUNTERS_EX2;

Диспетчер задач использует VM_COUNTERS_EX2 похож на следующий код:

VM_COUNTERS_EX2 vm;
ZwQueryInformationProcess(hProcess, ProcessVmCounters, &vm, sizeof(vm), 0);

Значение, которое он показывает для столбца «Память (частный рабочий набор)», является vm.PrivateWorkingSetSize поле.

Похоже, аналога Win32 API для этого не существует в настоящее время. Как вы можете увидеть это:

typedef struct _VM_COUNTERS_EX {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;// note this !!
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivateUsage;
} VM_COUNTERS_EX;

VM_COUNTERS_EX основа VM_COUNTERS_EX2 очень близко PROCESS_MEMORY_COUNTERS_EX но не точно (нет [Peak]VirtualSize) участники). GetProcessMemoryInfo() внутренние звонки ZwQueryInformationProcess(hProcess, ProcessVmCounters) а затем копирует VM_COUNTERS_EX в PROCESS_MEMORY_COUNTERS_EX,


В диспетчере задач в Windows 10 столбец «Память (физическая память, зарезервированная для отдельных процессов)» показывает PrivateWorkingSet (с шагом 1024 байта). Это же значение отображается на вкладке «Подробности» (частный рабочий набор). По неизвестной причине это значение отображается с шагом 1000 байтов, поэтому реальное значение всегда в 1,024 раза больше.

Но вы используете «общий» рабочий набор — WorkingSetSize — которая является суммой «частного» и «общего» рабочих наборов (вам нужно добавить столбцы добавления на вкладку Подробности, чтобы просмотреть это, по умолчанию отображается только личная память). Таким образом, существует постоянная разница в результате (14 МБ) — это «общий» рабочий набор (обычно это общие библиотеки DLL, например, ntdll.dll, kerner32.dll, kernelbase.dll, так далее). Эта разница не меняется при выделении памяти (10 000 фиктивных объектов). «Частный» рабочий набор увеличивается, но «общий» рабочий набор остается неизменным (поскольку новые DLL не загружаются / выгружаются).

Если вы хотите показать память, как это делает диспетчер задач, используйте PrivateWorkingSetSize член VM_COUNTERS_EX2 из NT API. Если вы не можете использовать это, то у вас будут другие результаты, чем в диспетчере задач.

Если вам не нравится NT API или вы не понимаете его, это не моя проблема (или, может быть, кто-то может сейчас получить PrivateWorkingSetSize используя какой-то «документированный» API?). Если диспетчер задач использует NT API, это тоже не мой выбор.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]