我目前正在使用this answer中的代码,并在评论中建议稍作修改。但是,无论我在内存中分配了多少个对象,列出的内存使用量总是比任务管理器列出的大约多14MB。为什么会这样?
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:
任务管理器:
资源监控:
分配10,000个虚拟对象时的结果:
debugText:
任务管理器:
资源监控:
修改
在使用资源监视器(perfmon)作为建议的注释后,我发现Working Set
的列与我正在使用的内存列表函数匹配。但是,我仍然感到困惑的是为什么Working Set
列和Private
列之间存在~14MB的差异(后者是任务管理器似乎使用的)。为什么会这样?
答案 0 :(得分:5)
任务管理器不使用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);
它显示的&#34;内存(私人工作集)&#34;列是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
的{{1}}基数非常接近VM_COUNTERS_EX2
但不完全(没有PROCESS_MEMORY_COUNTERS_EX
)成员)。 [Peak]VirtualSize
在内部调用GetProcessMemoryInfo()
,然后将ZwQueryInformationProcess(hProcess, ProcessVmCounters)
复制到VM_COUNTERS_EX
。
在Windows 10的任务管理器中,&#34;内存(由各个进程保留的物理内存)&#34;列显示PROCESS_MEMORY_COUNTERS_EX
(以1024字节为增量)。这个相同的值显示在&#34;详细信息&#34;标签(私人工作集)。由于未知原因,该值以1000字节为增量显示,因此实际值始终高出1.024倍。
但你使用&#34;总计&#34;工作集 - PrivateWorkingSet
- 这是&#34;私人&#34;的总和。和#34;分享&#34;工作集(您需要在“详细信息”选项卡中添加列以查看此内容,默认情况下仅显示私有内存)。因此,结果总是存在差异(14 MB) - 这就是&#34;共享&#34;工作集(通常是常见的DLL,如WorkingSetSize
,ntdll.dll
,kerner32.dll
等。分配内存(10,000个虚拟对象)时,这种差异不会改变。 &#34;私人&#34;工作集增长,但&#34;共享&#34;工作集保持不变(因为没有加载/卸载新的DLL)。
如果要像任务管理器一样显示内存,请使用NT API中kernelbase.dll
的{{1}}成员。如果你不能使用它,那么你将得到与任务管理器不同的结果。
如果您不喜欢NT API,或者不理解它,这不是我的问题(或者也许有人可以现在通过使用某些&#34;来获取PrivateWorkingSetSize
。记录&#34; API?)。如果任务管理器使用NT API,这也不是我的选择。