当前内存使用显示总是比任务管理器多 ~14MB
Current memory usage display is always ~14MB more than task manager
我目前正在使用 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
.
从Windows10开始,定义如下结构(在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);
它为 "Memory(private working set)" 列显示的值是 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 的任务管理器中,"Memory(physical memory reserved by individual processes)" 列显示 PrivateWorkingSet
(以 1024 字节为增量)。 "Details" 选项卡(私有工作集)下显示了相同的值。由于未知原因,该值以 1000 字节为增量显示,因此实际值始终高出 1.024 倍。
但是您使用 "total" 工作集 - WorkingSetSize
- 这是 "private" 和 "shared" 工作集的总和(您需要将列添加到详细信息选项卡查看此内容,默认情况下仅显示私有内存)。因此,结果存在恒定差异 (14 MB) - 这是 "shared" 工作集(通常是常见的 DLL,如 ntdll.dll
、kerner32.dll
、kernelbase.dll
等).当您分配内存(10,000 个虚拟对象)时,这种差异不会改变。 "private" 工作集增长,但 "shared" 工作集保持不变(因为没有新的 DLL loaded/unloaded)。
如果您想像任务管理器那样显示内存,请使用来自 NT API 的 VM_COUNTERS_EX2
的 PrivateWorkingSetSize
成员。如果您不能使用它,那么您将得到与任务管理器不同的结果。
如果你不喜欢 NT API,或者不理解它,这不是我的问题(或者也许有人可以 现在 得到 PrivateWorkingSetSize
通过使用一些 "documented" API?)。如果任务管理器使用NTAPI,这也不是我的选择
我目前正在使用 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
.
从Windows10开始,定义如下结构(在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);
它为 "Memory(private working set)" 列显示的值是 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 的任务管理器中,"Memory(physical memory reserved by individual processes)" 列显示 PrivateWorkingSet
(以 1024 字节为增量)。 "Details" 选项卡(私有工作集)下显示了相同的值。由于未知原因,该值以 1000 字节为增量显示,因此实际值始终高出 1.024 倍。
但是您使用 "total" 工作集 - WorkingSetSize
- 这是 "private" 和 "shared" 工作集的总和(您需要将列添加到详细信息选项卡查看此内容,默认情况下仅显示私有内存)。因此,结果存在恒定差异 (14 MB) - 这是 "shared" 工作集(通常是常见的 DLL,如 ntdll.dll
、kerner32.dll
、kernelbase.dll
等).当您分配内存(10,000 个虚拟对象)时,这种差异不会改变。 "private" 工作集增长,但 "shared" 工作集保持不变(因为没有新的 DLL loaded/unloaded)。
如果您想像任务管理器那样显示内存,请使用来自 NT API 的 VM_COUNTERS_EX2
的 PrivateWorkingSetSize
成员。如果您不能使用它,那么您将得到与任务管理器不同的结果。
如果你不喜欢 NT API,或者不理解它,这不是我的问题(或者也许有人可以 现在 得到 PrivateWorkingSetSize
通过使用一些 "documented" API?)。如果任务管理器使用NTAPI,这也不是我的选择