我目前正在使用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:

c – 当前内存使用情况显示总是比任务管理器多大约14MB教程


任务管理器:

c – 当前内存使用情况显示总是比任务管理器多大约14MB教程

资源监控:

c – 当前内存使用情况显示总是比任务管理器多大约14MB教程

分配10,000个虚拟对象时的结果:

debugText:

c – 当前内存使用情况显示总是比任务管理器多大约14MB教程

任务管理器:

c – 当前内存使用情况显示总是比任务管理器多大约14MB教程

资源监控:

c – 当前内存使用情况显示总是比任务管理器多大约14MB教程

编辑:

使用资源监视器(perfmon)作为建议的注释后,我发现Working Set的列与我正在使用的内存列表函数相匹配.但是,我仍然感到困惑的是,为什么工作集列和私有列之间存在~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字节为增量). “详细信息”选项卡(私有工作集)下显示相同的值.由于未知原因,该值以1000字节为增量显示,因此实际值总是高1.024倍.

但是你使用“总”工作集 – WorkingSetSize – 它是“私有”和“共享”工作集的总和(你需要在Details选项卡中添加列来查看它,默认情况下只显示私有内存) .因此,结果中存在恒定的差异(14 MB) – 这是“共享”工作集(通常是常见的DLL,如ntdll.dll,kerner32.dll,kernelbase.dll等).分配内存(10,000个虚拟对象)时,这种差异不会改变. “私有”工作集增长,但“共享”工作集保持不变(因为没有加载/卸载新的DLL).

如果要像任务管理器那样显示内存,请使用NT API中的VM\_COUNTERS\_EX2的PrivateWorkingSetSize成员.如果您不能使用它,那么您将获得与任务管理器不同的结果.

如果您不喜欢NT API,或者不理解它,这不是我的问题(或者现在有人可以通过使用一些“记录的”API来获取PrivateWorkingSetSize?).如果任务管理器使用NT API,这也不是我的选择.

标签: windows, memory, c, winapi, taskmanager

相关文章推荐

添加新评论,含*的栏目为必填