c ++ - Nuværende hukommelsesbrug er altid ~ 14MB mere end opgaveadministrator

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg bruger i øjeblikket koden i dette svar med nogle små ændringer som foreslået i kommentarerne. Uanset hvor mange objekter jeg tildeler i hukommelsen, er den angivne hukommelsesforbrug altid ~ 14MB mere end, hvad opgaveleder lister. Hvorfor kunne dette er?


std::stringstream ss;

PROCESS\_MEMORY\_COUNTERS\_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS\_MEMORY\_COUNTERS*)&pmc, sizeof(pmc));
SIZE\_T physMemUsedByMe = pmc.WorkingSetSize;

ss << "
MEM: " << (physMemUsedByMe / 1024 / 1024) << " MB";    

debugText.setString(ss.str());


Resultater på en normal bygning:


debugText:


debugText [32]


Task Manager:


Task Manager: [33]


Resource Monitor:


Resource Monitor [34]


Resultater ved tildeling af 10.000 dummy objekter:


debugText:


debugText [35]


Task Manager:


Task Manager [36]


Resource Monitor:


Resource Monitor [37]


EDIT:


Efter brug af Resource Monitor (perfmon) som kommentarerne foreslog, fandt jeg, at kolonnen for Working Set matcher den hukommelsesfortegnelse funktion, jeg bruger. Men jeg er stadig forvirret over hvorfor der er en forskel på 14 MB mellem kolonnen Working Set og kolonnen Private (den sidstnævnte er, hvad Task Manager synes at bruge). Hvorfor er dette tilfældet?

Bedste reference


Task Manager bruger ikke Win32 API GetProcessMemoryInfo() funktionen. Den bruger funktionen NT API ZwQueryInformationProcess() og indstiller parameteren ProcessInformationClass til ProcessVmCounters.


Begyndende i Windows 10 defineres følgende struktur (i ntddk.h):


typedef struct \_VM\_COUNTERS\_EX2 {
    VM\_COUNTERS\_EX CountersEx;
    SIZE\_T PrivateWorkingSetSize;
    ULONGLONG SharedCommitUsage;
} VM\_COUNTERS\_EX2, *PVM\_COUNTERS\_EX2;


Task Manager bruger VM\_COUNTERS\_EX2 svarende til følgende kode:


VM\_COUNTERS\_EX2 vm;
ZwQueryInformationProcess(hProcess, ProcessVmCounters, &vm, sizeof(vm), 0);


Værdien den viser for kolonnen 'Hukommelse (privat arbejdssæt)' er feltet vm.PrivateWorkingSetSize.


Det ligner en Win32 API-analog, da dette ikke findes på nuværende tidspunkt. Sådan kan du se dette:


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 base af VM\_COUNTERS\_EX2 er meget nær PROCESS\_MEMORY\_COUNTERS\_EX, men ikke eksakt (der er ingen [Peak]VirtualSize medlemmer). GetProcessMemoryInfo() internt kalder ZwQueryInformationProcess(hProcess, ProcessVmCounters) og kopierer derefter VM\_COUNTERS\_EX til PROCESS\_MEMORY\_COUNTERS\_EX.





I Opgavestyring på Windows 10 viser kolonnen 'Hukommelse (fysisk hukommelse reserveret af individuelle processer)' PrivateWorkingSet (i trin på 1024 byte). Denne samme værdi vises under fanen 'Detaljer' (privat arbejdssæt). Af en ukendt årsag er denne værdi vist i trin på 1000 byte, så den reelle værdi er altid 1.024 gange højere.


Men du bruger det 'samlede' arbejdssæt - WorkingSetSize - som er summen af ​​de 'private' og 'delte' arbejdsgrupper (du har brug for tilføjelsessøjlerne til fanen Detaljer for at se dette, som standard kun den private hukommelsen er vist). Så der er en konstant forskel i resultatet (14 MB) - dette er det 'delte' arbejdssæt (normalt almindelige DLL'er, som ntdll.dll, kerner32.dll, kernelbase.dll osv.). Denne forskel ændres ikke, når du tildeler hukommelse (10.000 dummy objekter). Det 'private' arbejdssæt vokser, men det 'delte' arbejdssæt forbliver uændret (fordi ingen nye DLL'er er indlæst/loset).


Hvis du vil vise hukommelse som Task Manager, skal du bruge PrivateWorkingSetSize medlem af VM\_COUNTERS\_EX2 fra NT API. Hvis du ikke kan bruge det, har du forskellige resultater end Task Manager.


Hvis du ikke kan lide NT API, eller forstår det ikke, er dette ikke mit problem (eller måske kan nogen nu få PrivateWorkingSetSize ved at bruge noget 'dokumenteret' API?). Hvis Task Manager bruger NT API, er dette heller ikke mit valg.