我目前正在使用 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());
正常构建的结果:
调试文本:
任务管理器:
资源监视器:
分配 10,000 个虚拟对象时的结果:
调试文本:
任务管理器:
资源监视器:
编辑:
按照评论建议使用资源监视器 (perfmon) 后,我发现 Working Set
列与我正在使用的内存列表功能相匹配。但是,我仍然对为什么 Working Set
列和 Private
列之间存在 ~14MB 的差异感到困惑(后者是任务管理器似乎使用的).为什么会这样?
最佳答案
任务管理器不使用 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_EX2
的 VM_COUNTERS_EX
基数非常接近 PROCESS_MEMORY_COUNTERS_EX
但不精确(没有 [Peak]VirtualSize
) 成员)。 GetProcessMemoryInfo()
在内部调用 ZwQueryInformationProcess(hProcess, ProcessVmCounters)
,然后将 VM_COUNTERS_EX
复制到 PROCESS_MEMORY_COUNTERS_EX
。
在 Windows 10 的任务管理器中,“内存(由各个进程保留的物理内存)”列显示 PrivateWorkingSet
(以 1024 字节为增量)。这个相同的值显示在“详细信息”选项卡(私有(private)工作集)下。由于未知原因,该值以 1000 字节为增量显示,因此实际值始终高出 1.024 倍。
但您使用“总”工作集 - WorkingSetSize
- 它是“私有(private)”和“共享”工作集的总和(您需要在“详细信息”选项卡中添加列才能查看此,默认情况下仅显示私有(private)内存)。因此,结果始终存在差异 (14 MB) - 这是“共享”工作集(通常是常见的 DLL,如 ntdll.dll
、kerner32.dll
, kernelbase.dll
等)。当您分配内存(10,000 个虚拟对象)时,这种差异不会改变。 “私有(private)”工作集增长,但“共享”工作集保持不变(因为没有加载/卸载新的 DLL)。
如果您想像任务管理器那样显示内存,请使用 NT API 中 VM_COUNTERS_EX2
的 PrivateWorkingSetSize
成员。如果您不能使用它,那么您将得到与任务管理器不同的结果。
如果您不喜欢 NT API,或者不理解它,这不是我的问题(或者也许有人可以现在通过使用一些“记录在案的“API?”。如果任务管理器使用 NT API,这也不是我的选择。
关于c++ - 当前内存使用显示总是比任务管理器多 ~14MB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42986220/