c ++ - Hvilken del af processens virtuelle hukommelse viser Windows Task Manager

Indlæg af Hanne Mølgaard Plasc

Problem



Mit spørgsmål er lidt naivt. Jeg er villig til at få et overblik så simpelt som muligt og kunne ikke finde nogen ressource, der gjorde det klart for mig. Jeg er en udvikler, og jeg vil forstå, hvad nøjagtigt er hukommelsen, der vises i kolonnen 'hukommelse' som standard i Windows Task Manager:


Indtast billedbeskrivelse her [7]


For at gøre tingene lidt enklere, lad os glemme den hukommelse processen deler med andre processer, og forestil dig, at den delte hukommelse er ubetydelig. Også jeg fokuserede på det store billede og primært pleje ting på GB-niveau.


Så vidt jeg ved, gemmes hukommelsen reserveret af processen kaldet 'virtuel hukommelse', delvist i hovedhukommelsen (RAM), dels på disken. Systemet bestemmer, hvad der skal hen. Systemet holder grundlæggende i RAM de dele af den virtuelle hukommelse, der bliver adgang til tilstrækkeligt ofte af processen. En proces kan reservere mere virtuel hukommelse end RAM, der er tilgængelig i computeren.


Ud fra et udviklingsperspektiv kan den virtuelle hukommelse kun delvist tildeles af programmet via sin egen hukommelsesleder (med f.eks. malloc() eller new X(). Jeg antager, at systemet ikke har nogen bevidsthed om, hvilken del af den virtuelle hukommelse der tildeles, da dette håndteres af processen på en 'privat' måde og afhænger af sproget, runtime, compiler ... Q: Er dette korrekt?


Min hypotese er, at hukommelsen, der vises af task manager, er i det væsentlige den del af den virtuelle hukommelse, der lagres i RAM af systemet. Q: Er det korrekt? Og er der en enkel måde at kende den samlede virtuelle hukommelse reserveret af processen?

Bedste reference


Hukommelse på Windows er ... ekstremt kompliceret og spørger 'hvor meget hukommelse gør min proces brug' er effektivt et nonsensisk spørgsmål. For at besvare dine spørgsmål kan vi først få en lille baggrund.


Hukommelse på Windows er tildelt via ptr = VirtualAlloc(..., MEM\_RESERVE, ...) og begået senere med VirtualAlloc(ptr+n, MEM\_COMMIT, ...).


Enhver reserveret hukommelse bruger bare op adresselokal, og det er ikke interessant. Windows vil lade dig MEM\_RESERVE terabyte af hukommelse bare fint. Forbindelsen gør brug af ressourcer, men ikke som du tror. Når du ringer til commit windows, fungerer nogle summer og i det væsentlige (total fysisk ram + total swap - nuværende commit) og lader dig allokere hukommelse, hvis der er nok ledig. MEN Windows-hukommelseslederen giver dig ikke fysisk ramme indtil du bruger det faktisk.


Senere, men hvis vinduerne er stramme for fysisk RAM, vil det bytte noget af dit RAM ud på disken (det kan komprimere det og også smide ubrugte sider, smide alt, der er direkte kortlagt fra en fil og andre optimeringer) .Det betyder, at din total commit og total fysisk ram brug for dit program kan være vildt forskellige. Begge tal er nyttige afhængigt af hvad du måler.


Der er en sidste stor advarsel - hukommelse, der deles. Når du læser DLL'er, er koden, den skrivebeskyttede hukommelse [[og endda måske læs/skrive sektionen, men dette er COW 'd]] kan deles med andre programmer. Det betyder, at din app kræver den hukommelse, men du kan ikke tælle den hukommelse mod din app - den kan jo deles, og så optager du ikke så meget fysisk hukommelse som et naivt tæller ville tro.


(Hvis du skriver et spil eller lignende, skal du også tælle GPU-hukommelse, men jeg er ikke ekspert her)


Alt ovenstående godhed er normalt indpakket af den bunke, applikationen bruger, og du ser ingen af ​​dette - du beder om og bruger hukommelse. Og det er lige så optimalt som muligt.


Du kan se dette ved at gå til fanen Detaljer og se på de forskellige muligheder - Forbindelsesstørrelse og arbejdssæt er virkelig nyttige. Hvis du bare kigger på hovedvinduet i task manager og det har en enkelt værdi, håber jeg at du forstår nu, at en enkelt værdi for den anvendte hukommelse skal være et slags kompromis, da det ikke er et spørgsmål, der giver mening.


Nu for at besvare dine spørgsmål


For det første ved OS'et præcis, hvor meget hukommelse din app har reserveret og hvor meget den har forpligtet sig. Hvad det ikke ved, er, hvis den høje implementering du (eller mere sandsynligt CRT) bruger, har bevaret en frigivet hukommelse, som den ikke har frigivet tilbage til operativsystemet. Hopper gør dette ofte som en optimering - beder om hukommelse fra operativsystemet og frigiver det tilbage til operativsystemet er en temmelig dyr operation (og kan kun gøres i store klumper, der er kendt som sider), og så holder de fleste rundt omkring.


Andet spørgsmål: Brug ikke den værdi, gå til detaljer og brug værdierne der som kun du ved hvad du rent faktisk vil spørge.


REDIGERE:


Til din kommentar, ja, men det afhænger af størrelsen af ​​tildelingen. Hvis du tildeler en stor blok af hukommelse (siger>=1 MB), hæmmer bunken i CRT generelt tildelingen til operativsystemet, og så frigivelse af de enkelte vil faktisk frigøre dem. For små tildelinger beder bunken i CRT efter sider med hukommelse fra operativsystemet og opdeler det derefter for at give ud i tildelinger. Og så hvis du så frigiver hver anden af ​​dem, vil du blive efterladt af huller - og bunken kan ikke give disse huller tilbage til OS'en, da OS normalt kun virker i hele sider. Så alt hvad du ser i task manager viser, at al hukommelse bruges stadig. Husk at denne hukommelse ikke er tabt eller lækket, den samles simpelthen effektivt og vil blive brugt igen, hvis tildelinger beder om den størrelse. Hvis du bekymrer dig om denne hukommelse, kan du bruge crt heap statistik famliy of funktioner til at holde øje med dem - specifikt \_CrtMemDumpStatistics [8]