问题描述
我目前正在使用,并根据注释中的建议进行了一些细微修改.但是,无论我在内存中分配了多少个对象,列出的内存使用率始终比任务管理器列出的内存大14MB.为什么会这样?
I'm currently using the code in this answer, with some slight modifications as suggested in the comments. However, no matter how many objects I allocate in memory, the listed memory usage is always ~14MB more than what task manager lists. Why could this be?
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:
任务管理器:
资源监控器:
使用Resource Monitor(perfmon)作为注释建议后,我发现Working Set
的列与我正在使用的内存列表功能匹配.但是,我仍然困惑为什么Working Set
列和Private
列之间有〜14MB的差异(后者是Task Manager似乎使用的).为什么会这样?
After using Resource Monitor (perfmon) as the comments suggested, I found that the column for Working Set
matches the memory-listing function I'm using. However, I'm still perplexed as to why there's a ~14MB difference between the Working Set
column and the Private
column (the latter of which is what Task Manager appears to use). Why is this the case?
推荐答案
任务管理器不使用Win32 API GetProcessMemoryInfo()
函数.它使用NT API ZwQueryInformationProcess()
函数,将ProcessInformationClass
参数设置为ProcessVmCounters
.
Task Manager does not use the Win32 API GetProcessMemoryInfo()
function. It uses the NT API ZwQueryInformationProcess()
function, setting the ProcessInformationClass
parameter to ProcessVmCounters
.
从Windows 10开始,定义了以下结构(在ntddk.h
中):
Beginning in Windows 10, the following structure is defined (in 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
类似于以下代码:
Task Manager uses VM_COUNTERS_EX2
similar to the following code:
VM_COUNTERS_EX2 vm;
ZwQueryInformationProcess(hProcess, ProcessVmCounters, &vm, sizeof(vm), 0);
在内存(专用工作集)"列中显示的值是vm.PrivateWorkingSetSize
字段.
The value it shows for the "Memory(private working set)" column is the vm.PrivateWorkingSetSize
field.
目前看来还没有Win32 API类似物.您如何看待这一点:
It looks like a Win32 API analog for this does not exist at this time. How you can see this:
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
.
The VM_COUNTERS_EX
base of VM_COUNTERS_EX2
is very near PROCESS_MEMORY_COUNTERS_EX
but not exact (there are no [Peak]VirtualSize
) members). GetProcessMemoryInfo()
internally calls ZwQueryInformationProcess(hProcess, ProcessVmCounters)
and then copies the VM_COUNTERS_EX
to PROCESS_MEMORY_COUNTERS_EX
.
在Windows 10的任务管理器中,内存(单个进程保留的物理内存)"列显示PrivateWorkingSet
(以1024字节为增量).此相同的值显示在详细信息"选项卡(专用工作集)下.出于未知原因,该值以1000字节为增量显示,因此实际值始终高出1.024倍.
In Task Manager on Windows 10, the "Memory(physical memory reserved by individual processes)" column shows PrivateWorkingSet
(in increments of 1024 bytes). This same value is shown under the "Details" tab (private working set). For an unknown reason, that value is shown in increments of 1000 bytes, so the real value is always 1.024 times higher.
但是您使用总计"工作集-WorkingSetSize
-这是私有"和共享"工作集的总和(您需要在详细信息"选项卡中添加列才能查看此内容,默认情况下仅显示私有内存).因此,结果之间存在恒定的差异(14 MB)-这是共享的"工作集(通常是常见的DLL,例如ntdll.dll
,kerner32.dll
,kernelbase.dll
等).分配内存(10,000个虚拟对象)时,这种差异不会改变. 专用"工作集在增长,但是共享"工作集保持不变(因为没有新的DLL被加载/卸载).
But you use the "total" working set - WorkingSetSize
- which is the sum of the "private" and "shared" working sets (you need the add columns to the Details tab to view this, by default only the private memory is shown). So, there is a constant difference in the result (14 MB) - this is the "shared" working set (usually common DLLs, like ntdll.dll
, kerner32.dll
, kernelbase.dll
, etc). This difference does not change when you allocate memory (10,000 dummy objects). The "private" working set grows, but the "shared" working set remains unchanged (because no new DLLs are loaded/unloaded).
如果要像任务管理器一样显示内存,请使用NT API中VM_COUNTERS_EX2
的PrivateWorkingSetSize
成员.如果您不能使用它,那么您将获得与任务管理器不同的结果.
If you want to show memory like Task Manager does, use the PrivateWorkingSetSize
member of VM_COUNTERS_EX2
from the NT API. If you cannot use that, then you will have different results than Task Manager.
如果您不喜欢NT API或不理解它,这不是我的问题(或者也许有人可以 now 通过使用一些已记录的" API来获得PrivateWorkingSetSize
?) .如果任务管理器使用NT API,这也不是我的选择.
If you do not like the NT API, or do not understand it, this is not my problem (or maybe somebody can now get the PrivateWorkingSetSize
by using some "documented" API?). If Task Manager uses the NT API, this is also not my choice.
这篇关于当前的内存使用情况显示始终比任务管理器大14MB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!