Che cosa significa davvero l'«utilizzo della memoria» di Windows — Leggere correttamente Working Set, Private Bytes, Commit e il file di paging
· Go Komura · Windows, Sviluppo Windows, Gestione della memoria, Working Set, Private Bytes, Commit, File di paging, Monitoraggio delle prestazioni, Risoluzione dei problemi, Sysinternals
Gestione attività mostra la «Memoria» di un processo come 1,2 GB. Eppure Process Explorer mostra un Working Set di 1,5 GB e Private Bytes di 2,4 GB, e la Size di VMMap è ancora più grande. Guardando il sistema nel complesso, si legge «Committed 19.6/31.8GB».
Allora quanti gigabyte di memoria sta usando davvero questa app, alla fine?
La risposta è che quale numero guardare dipende da che cosa volete sapere davvero. L’indicatore da usare cambia a seconda che vogliate la quantità attualmente residente in RAM, la quantità allocata specificamente a quel processo, la quantità che il sistema ha promesso di continuare a coprire, o semplicemente l’intervallo di indirizzi virtuali che è stato riservato.
Ciò che rende confusi gli indicatori di memoria di Windows è che sono tutti mostrati sotto la stessa parola, «memoria», anche se in realtà misurano i seguenti assi distinti.
- Quanto spazio di indirizzi è in uso
- Quanto commit è stato consumato
- Se è attualmente residente nella RAM fisica
- Se la pagina è privata del processo, o condivisibile
- Quanto allocazione in più il sistema nel complesso può ancora sostenere
Questo articolo è rivolto a chi indaga una memoria dell’app in crescita o una carenza di memoria a livello di sistema su Windows 10/11 e l’attuale Windows Server, e collega in un solo quadro i rapporti tra Working Set, Private Working Set, Private Bytes, Commit, Virtual Bytes, il file di paging, Available e i page fault.
La procedura per capire perché gli oggetti .NET non vengono raccolti è trattata in dettaglio in «Distinguere il ritardo del GC da una perdita di memoria in .NET», e l’uso concreto di VMMap e Process Explorer in «Process Explorer / Handle / VMMap in pratica». Questo articolo si concentra sul prerequisito di entrambi: come leggere i numeri dal lato del sistema operativo Windows.
1. Prima di tutto, la conclusione
- Working Set è l’insieme delle pagine attualmente residenti in RAM. Include non solo le pagine private del processo ma anche pagine che si possono condividere con altri processi, come il codice delle DLL e i file mappati in memoria.1
- Private Working Set è la porzione del Working Set che attualmente appartiene solo a quel processo. È utile come approssimazione di «la RAM che questo processo da solo occupa ora», ma non è la quantità totale che l’app ha allocato.2
- Private Bytes è la quantità di commit privata di quel processo. È un indicatore distinto dal fatto che la memoria sia attualmente residente in RAM. Anche il campo
PagefileUsagenella struttura Win32 API, sull’attuale Windows, rappresenta di fatto lo stesso Commit Charge, e non i byte realmente scritti nel file di paging.2 - «Committed X/Y» di Gestione attività mostra X come il commit totale attuale del sistema e Y come il tetto di commit. X non è l’uso del file di paging. Y è determinato grosso modo da RAM più file di paging.3
- Reserve e Commit sono cose diverse. Limitarsi a Reserved un intervallo di indirizzi virtuali lo mette da parte per un uso futuro; non consuma la stessa quantità né di RAM né di tetto di commit.45
- Un Page Fault non significa necessariamente I/O su disco. Ci sono i soft fault, che si risolvono dentro la RAM, e i hard fault, che leggono dal file di paging, dai file eseguibili, dai file mappati in memoria e simili.16
- Una perdita di memoria si giudica non da una sola lettura ma dalla tendenza quando si ripete lo stesso carico. In particolare, osservate se Private Bytes e la sua scomposizione continuano a salire a scalini anche dopo la fine dell’elaborazione, senza tornare allo stesso stato stazionario.
In una frase: Working Set è «la quantità ora in RAM», Private Bytes è «la quantità promessa specificamente a questo processo», e Commit è «la quantità che il sistema nel complesso ha promesso».
flowchart TB
accTitle: Scegliere l'indicatore di memoria Windows giusto
accDescr: Quale indicatore guardare dipende dal fatto che vogliate la residenza in RAM, il commit privato del processo, il commit di sistema o l'intervallo di indirizzi virtuali
question["Che cosa volete sapere sull'uso della memoria"]
question -->|quantità ora in RAM| workingSet["Working Set"]
question -->|quantità promessa privata del processo| privateBytes["Private Bytes"]
question -->|quantità promessa a livello di sistema| systemCommit["System Commit"]
question -->|intervallo di indirizzi riservato| virtualBytes["Virtual Bytes / Reserved"]
workingSet --> resident["Residenza nella RAM fisica"]
privateBytes --> privateCommit["Commit privato del processo"]
systemCommit --> commitLimit["Confronto con il Commit Limit"]
virtualBytes --> addressSpace["Spazio di indirizzi virtuale"]
Figura 1: Scomponete prima l’osservazione «la memoria è alta» in quattro domande distinte.
2. Dividere l’«utilizzo della memoria» in quattro assi
Per cominciare, pensate alla memoria di Windows non come a «una sola barra» ma lungo quattro assi.
flowchart TB
accTitle: Quattro assi indipendenti per classificare una sola pagina
accDescr: Controllate separatamente lo stato dell'indirizzo virtuale, la copertura delle pagine committed, la residenza nella RAM fisica e la condivisibilità con altri processi
page["Guardate una pagina su quattro assi"]
page --> address["Stato dell'indirizzo"]
address --> addressValues["Free / Reserved / Committed"]
page --> backing["Copertura"]
backing --> backingValues["Page-file-backed / File-backed"]
page --> residentAxis["Residenza in RAM"]
residentAxis --> residentValues["Resident / Not resident"]
page --> sharing["Condivisibilità"]
sharing --> sharingValues["Private / Shareable"]
Figura 2: Anche per una sola pagina, stato dell’indirizzo, copertura, residenza e condivisibilità si determinano ciascuno in modo indipendente.
Mapped non è uno stato di indirizzo accanto a Free, Reserved e Committed — è una categoria di regione. Anche le pagine in una vista mappata possono essere Committed. Allo stesso modo, Private non è un mezzo di copertura ma una classificazione di condivisibilità. Quindi leggete la copertura come Page-file-backed o File-backed, e la condivisibilità come Private o Shareable, separatamente.
Combinando questi quattro assi il rapporto tra gli indicatori rappresentativi è il seguente.
| Stato della pagina | Working Set | Private Working Set | Private Bytes | Famiglia Virtual Bytes |
|---|---|---|---|---|
| Privata del processo, committed, residente in RAM | Inclusa | Inclusa | Inclusa | Inclusa |
| Privata del processo, committed, non residente in RAM | Non inclusa | Non inclusa | Inclusa | Inclusa |
| Pagina condivisa di una DLL o di un file mappato, residente in RAM | Inclusa | In genere non inclusa | In genere non inclusa | Inclusa |
| Reserved ma non committed | Non inclusa | Non inclusa | Non inclusa | Può essere inclusa |
| Intervallo di indirizzi inutilizzato | Non inclusa | Non inclusa | Non inclusa | Di solito non inclusa |
flowchart TB
accTitle: Corrispondenza tra tipi di pagina e indicatori di memoria principali
accDescr: Mostra quali indicatori includono le pagine private residenti, le private non residenti, le condivise residenti e gli intervalli solo riservati
privateResident["Private, committed, residente in RAM"]
privateNonresident["Private, committed, non residente in RAM"]
sharedResident["Pagina condivisa, residente in RAM"]
reservedOnly["Reserved, non committed"]
workingSet["Working Set"]
privateWorkingSet["Private Working Set"]
privateBytes["Private Bytes"]
virtualBytes["Famiglia Virtual Bytes"]
privateResident --> workingSet
privateResident --> privateWorkingSet
privateResident --> privateBytes
privateResident --> virtualBytes
privateNonresident --> privateBytes
privateNonresident --> virtualBytes
sharedResident --> workingSet
sharedResident --> virtualBytes
reservedOnly --> virtualBytes
Figura 3: Working Set e Private Bytes contano insiemi diversi di pagine, quindi non sono in un semplice rapporto di inclusione.
Il punto importante qui è che Working Set e Private Bytes non sono in un semplice rapporto di inclusione.
Private Bytes include pagine private del processo ma non attualmente residenti in RAM. Working Set, d’altra parte, include pagine condivise — come il codice delle DLL e la memoria condivisa — che Private Bytes non conta affatto. Quindi, a seconda del processo e del momento, Working Set può essere maggiore di Private Bytes, o il contrario.
Inoltre, sommare semplicemente i Working Set di più processi può contare la stessa pagina fisica — ad esempio una DLL condivisa — più di una volta. «La somma del Working Set di ciascun processo è uguale alla RAM in uso» non vale necessariamente.
3. Spazio di indirizzi virtuale — Reserve e Commit sono cose diverse
3.1. Un indirizzo virtuale non è un indirizzo di RAM fisica
Ogni processo ha il proprio spazio di indirizzi virtuale privato. Un puntatore con cui lavora un’app non indica direttamente una posizione nella RAM fisica; Windows usa le tabelle delle pagine per mappare gli indirizzi virtuali su pagine fisiche o su dati su un file.7
Di conseguenza, anche su un PC con 64 GB di RAM installata, lo spazio di indirizzi virtuale che un dato processo a 32 bit può usare è di norma molto più piccolo. Viceversa, è altrettanto normale che un processo a 64 bit abbia uno spazio di indirizzi virtuale più grande della RAM fisica.
3.2. Reserved significa solo «l’indirizzo è stato prenotato»
MEM_RESERVE di VirtualAlloc riserva un intervallo contiguo di indirizzi virtuali per un uso futuro. A questo stadio nessun archivio fisico è associato alle pagine, e l’intervallo non si può leggere né scrivere.45
Per esempio, anche se un database o un runtime riserva un intervallo di indirizzi di 8 GB per la crescita futura, questo da solo non consuma 8 GB di RAM né 8 GB di Private Bytes.
3.3. Committed è una promessa di «coprirla quando servirà»
MEM_COMMIT è l’operazione che mette una pagina virtuale nello stato Committed e fa promettere a Windows di fornire la copertura necessaria. Se la lettura, la scrittura o l’esecuzione siano realmente permesse lo decide a parte la protezione della pagina — PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE, PAGE_NOACCESS e così via — quindi essere Committed da sola non significa «leggibile e scrivibile». Nel momento in cui è committed viene conteggiata verso il Commit Charge del sistema, ma la pagina fisica effettiva può non essere assegnata fino al primo accesso. Una pagina toccata per la prima volta viene azzerata, passa per un demand-zero fault ed entra nel Working Set.51
Quindi, anche se in entrambi i casi lo chiamiamo «allocato», in realtà ci sono i tre stadi seguenti.
flowchart TB
accTitle: Tre stadi da Reserve attraverso Commit alla residenza in RAM
accDescr: Mostra il flusso di riservare un indirizzo virtuale, fare commit della pagina e far sì che il primo accesso assegni una pagina fisica e entri nel Working Set
reserve["MEM_RESERVE - riservare un intervallo"]
reserve -.-> virtualMetric["Si riflette nella famiglia Virtual Bytes"]
reserve -->|MEM_COMMIT| committed["Committed - accessibile secondo la protezione"]
committed -.-> commitMetric["Si riflette in Private Bytes / System Commit"]
committed -->|primo accesso, demand-zero fault| resident["Pagina fisica assegnata, residente in RAM"]
resident -.-> workingSetMetric["Si riflette nel Working Set"]
committed -.->|se non si accede mai| nonresident["Committed ma non residente"]
Figura 4: Reserve, Commit e il primo accesso sono eventi distinti, e ciascuno muove un indicatore diverso.
Questi tre stadi muovono separatamente, rispettivamente, i numeri della famiglia Virtual Bytes, di Private Bytes e del Working Set.
3.4. Perché si può avere OutOfMemory anche con RAM libera
Se un’allocazione di memoria riesce non è determinato dalla sola RAM libera.
- Il processo ha esaurito il proprio spazio di indirizzi virtuale
- Non c’è un intervallo di indirizzi libero della dimensione richiesta che sia contiguo
- Il Commit Charge a livello di sistema ha raggiunto il Commit Limit
- Un Job Object, un container, un runtime o una libreria ha un proprio limite
- È un processo a 32 bit
- L’heap nativo è frammentato
Anche su Windows a 64 bit, lo spazio di indirizzi virtuale in modalità utente di un processo a 32 bit è di norma 2 GB se IMAGE_FILE_LARGE_ADDRESS_AWARE non è impostato. Un’app a 32 bit con quel flag può usare fino a 4 GB su Windows a 64 bit.8
Quindi «il PC ha 20 GB di RAM libera, eppure l’app a 32 bit fallisce intorno a 1,6 GB» non è una contraddizione. Potrebbe non essere affatto un problema di RAM, ma frammentazione dello spazio di indirizzi o lo scontro con un limite rigido.
4. Working Set — le pagine attualmente in RAM
Working Set è l’insieme delle pagine, nello spazio di indirizzi virtuale di un processo, che sono attualmente residenti nella RAM fisica.1
Questo insieme è un misto di quanto segue.
- Heap e stack propri del processo
- Codice e dati in sola lettura di EXE e DLL
- File mappati in memoria
- Memoria condivisa
- Pagine diventate private di quel processo dopo il copy-on-write
- Pagine toccate dal runtime e da varie librerie
4.1. Un Working Set in crescita non significa necessariamente che si sia allocato di più
Accedere per la prima volta a una pagina già committed può aumentare solo il Working Set mentre Private Bytes resta invariato. Allo stesso modo, quando un file grande viene mappato in memoria e letto in sequenza, le pagine coperte dal file entrano nel Working Set mentre Private Bytes quasi non aumenta.
Viceversa, quando Windows fa Trim del Working Set in risposta alla pressione di memoria, si riduce solo il Working Set mentre l’app tiene logicamente ancora la stessa memoria. Toccarla di nuovo in seguito la riporta attraverso un Page Fault.
Quindi un calo del Working Set non significa necessariamente «l’app l’ha liberata», e un rialzo non significa necessariamente «l’app l’ha appena allocata».
flowchart TB
accTitle: Un flusso tipico in cui sale e scende solo il Working Set
accDescr: La stessa pagina committed entra in RAM al primo accesso, diventa non residente al Trim e torna al riaccesso, mentre Private Bytes continua a essere conteggiato
committed["La stessa pagina committed"]
committed -->|primo accesso| resident["Residente in RAM"]
resident -->|Trim sotto pressione di memoria| nonresident["Non residente"]
nonresident -->|Page Fault al riaccesso| resident
resident -.-> inWorkingSet["Inclusa nel Working Set"]
nonresident -.-> outsideWorkingSet["Non inclusa nel Working Set"]
committed -.-> privateBytes["Contata in Private Bytes finché committed"]
Figura 5: Il Working Set sale e scende con la residenza, ma Private Bytes non diminuisce finché resta il commit sulla stessa pagina.
4.2. Il Working Set include pagine condivise
Se 10 processi condividono le pagine di codice della stessa DLL, quella pagina può comparire nel Working Set di ciascun processo, anche se in RAM fisica esiste una sola copia. Che la somma dei Working Set superi la RAM installata non è di per sé un segnale di problema.
Se volete avvicinarvi a «la RAM che questo processo da solo occupa ora», guardate Private Working Set. Anche così, non è «tutta la memoria che quel processo ha allocato» — è strettamente le pagine private attualmente residenti.
4.3. Forzare giù il Working Set non sistema una perdita
Potete usare EmptyWorkingSet o SetProcessWorkingSetSize per evincere pagine dal Working Set di un processo. Ma questa non è un’operazione che libera commit o rilascia riferimenti sull’heap. L’uso apparente di RAM scende mentre Private Bytes resta invariato, e l’accesso successivo può innescare una raffica di page fault.9
Se la cifra di Gestione attività si riduce solo subito dopo aver premuto un pulsante «riduci memoria», e risale immediatamente quando riprendete a lavorare, può essere solo un Trim del Working Set e non un vero «rilascio».
5. Private Bytes — la quantità di commit privata di un processo
Private Bytes è la quantità di memoria virtuale committed esclusivamente per quel processo. Rappresenta Commit Charge che non si può condividere con un altro processo, e non importa se sia attualmente residente in RAM. In PROCESS_MEMORY_COUNTERS_EX di Microsoft, PrivateUsage corrisponde a questo valore.102
L’API Win32 ha anche un campo dal nome fuorviante, PagefileUsage, ma la documentazione attuale lo definisce come «il Commit Charge di quel processo» e afferma che è lo stesso valore di PrivateUsage. In altre parole, Private Bytes di 2 GB non significa «2 GB sono stati scritti in pagefile.sys».2
Private Bytes è tipicamente influenzato da quanto segue.
- Il commit dell’heap nativo usato da
HeapAlloc,malloc,newe simili - Private Data committed direttamente con
VirtualAlloc - La regione committed dell’heap GC di .NET
- La porzione di uno stack di thread che è stata realmente committed
- Il Commit Charge per l’intera vista riservata quando si mappa una vista copy-on-write(
FILE_MAP_COPY) - I buffer privati tenuti internamente da librerie e SDK di dispositivi
In una vista copy-on-write creata con FILE_MAP_COPY, ogni pagina potrebbe alla fine diventare privata, quindi al momento del mapping Windows riserva Commit Charge sufficiente a coprire l’intera vista con il file di paging. Per questo System Commit e il Commit Charge del processo(Private Bytes)possono salire della dimensione dell’intera vista ancora prima che una scrittura crei davvero una copia privata.11
5.1. Perché Private Bytes non scende dopo free o un GC
Anche quando la memoria è «liberata» dal punto di vista dell’applicazione, il runtime o l’allocatore dell’heap può non fare Decommit di quella regione all’OS, e invece trattenerla per un riuso futuro. In quel caso Private Bytes resta alto anche se la regione è riutilizzabile internamente all’interno dell’app.
Può anche restare alto per ragioni come il fatto che sia ancora viva solo una parte di una regione grande, la frammentazione, o una cache o un pool che si è riscaldato fino al tetto.
Quindi un Private Bytes alto da solo non prova una perdita. Ciò che dovete guardare è un confronto nel tempo:
- Ripetete la stessa elaborazione lo stesso numero di volte
- Attendete lo stesso tempo dopo l’elaborazione
- Controllate se Private Bytes torna allo stesso livello, o si attesta a un valore fisso
- Usate VMMap o un dump dell’heap per controllare quale regione o tipo è cresciuto
flowchart TB
accTitle: Perché Private Bytes non scende dopo free o un GC
accDescr: Private Bytes cambia in modo diverso a seconda che l'allocatore restituisca all'OS una regione di cui l'app non ha più bisogno, o la trattenga per il riuso
release["L'app libera una regione via free / GC"]
release --> decision{"L'allocatore la restituisce all'OS"}
decision -->|Decommit / Release| returned["Il Commit Charge diminuisce"]
returned --> lower["Private Bytes scende"]
decision -->|la trattiene per il riuso| retained["La regione resta committed"]
retained --> high["Private Bytes resta alto"]
retained --> reasons["Pool, cache, frammentazione"]
Figura 6: Che una regione diventi riutilizzabile dentro l’app non è la stessa cosa che il suo Commit venga restituito all’OS.
5.2. Un andamento candidato forte per una perdita
Un aumento come il seguente, in cui il pavimento sale a «scalini» a ogni giro di carico, merita attenzione.
Private Bytes
^
| ________
| ______|
| ______|
|_____|
+----------------------------> Ripetizioni della stessa elaborazione
Detto questo, anche una forma a scalini può essere solo qualche giro di crescita da JIT di prima volta, font, decoder di immagini, pool di connessioni o riscaldamento della cache, dopo di che si stabilizza. Ciò che conta non è che stia aumentando, ma che non converga a uno stato stazionario.
6. System Commit — che cosa è davvero «Committed X/Y»
La cifra «Committed X/Y» nella scheda [Prestazioni] → [Memoria] di Gestione attività è un indicatore a livello di sistema.
- X: System Commit Charge — la memoria committed che Windows sta attualmente promettendo di coprire in tutto il sistema
- Y: System Commit Limit — il tetto di commit che il sistema può sostenere
Il Commit Limit è determinato grosso modo dalla RAM fisica più il totale di tutti i file di paging. Senza file di paging, risulta un po’ più piccolo della RAM installata.36
flowchart TB
accTitle: Il rapporto tra System Commit Charge e Commit Limit
accDescr: Il commit per-processo, delle sezioni condivise e del kernel forma il valore attuale X, mentre la RAM fisica e il file di paging sostengono il tetto Y
processCommit["Private Commit di ciascun processo"] --> charge["System Commit Charge - X"]
sharedCommit["Commit delle sezioni condivise coperte dal file di paging"] --> charge
kernelCommit["Commit del kernel"] --> charge
physicalRam["RAM fisica"] --> limit["System Commit Limit - Y"]
pageFiles["File di paging"] --> limit
charge -->|X non può superare Y| limit
Figura 7: X è la quantità promessa attuale e Y è il tetto che può sostenere quella promessa — non è una visualizzazione dell’uso del file di paging.
Il System Commit Charge include non solo la somma dei Private Bytes di ciascun processo, ma anche il Commit delle sezioni condivise coperte dal file di paging e il Commit consumato dal kernel. Quindi la sola somma dei Private Bytes per processo non può spiegare X per intero.
6.1. Il Commit Charge non è l’uso del file di paging
Prendete un sistema con 16 GB di RAM, un file di paging da 16 GB e Committed a 20/31 GB.
Quei 20 GB non significano «20 GB sono stati scritti nel file di paging». È la quantità totale che Windows sta promettendo di coprire con RAM o file di paging, quando servirà, per le pagine private scrivibili e simili.
In quel momento può valere un misto dei seguenti stati:
- La maggior parte è residente in RAM
- Una parte è stata paginata nel file di paging
- Una parte è committed ma non ha ancora avuto il primo accesso
- Una parte è consumata come commit dal lato kernel
Se volete vedere l’uso reale del file di paging, controllate Paging File(*)\% Usage separatamente dal Commit. Anche il materiale di Microsoft spiega che un alto uso del file di paging da solo non indica necessariamente un problema di prestazioni, e che va giudicato insieme al raggiungimento del Commit Limit, alla Modified Page List e all’I/O di paging effettivo.6
6.2. Che cosa succede avvicinandosi al Commit Limit
Quando il System Commit Charge raggiunge il Commit Limit, le nuove richieste di commit non possono essere coperte. Questo porta a fallimenti di allocazione della memoria dei processi, crash delle app e sistema che non risponde.3
Qui X/Y del Commit conta più della «RAM libera». Anche se fate Trim dei Working Set per liberare RAM, raggiungere il Commit Limit non si risolve a meno che non diminuisca il Commit Charge stesso.
6.3. I tre ruoli del file di paging
Il file di paging serve principalmente i seguenti ruoli.
- Estendere il Commit Limit
- Permettere di paginare fuori dalla RAM le pagine modificate usate di rado
- Coprire il dump di crash di sistema, a seconda della configurazione
Disabilitare il file di paging non è un caso semplice di «l’I/O su disco scende sempre e le cose diventano più veloci». Semmai abbassa il Commit Limit, rende più probabile che pagine modificate ma al momento inutili restino in RAM, e può rendere impossibile catturare il dump di cui avete bisogno quando avviene un crash.36
La dimensione appropriata del file di paging non si può decidere dalla sola RAM installata. Microsoft stessa spiega che non si può generalizzare, perché il picco di System Commit Charge e il tipo di dump di crash richiesto differiscono da sistema a sistema.6
7. La scomposizione della RAM fisica — non giudicate dal solo Available basso
La RAM fisica non è usata solo dai Working Set dei processi utente.
- Il Working Set di ciascun processo
- La cache dei file di sistema
- Elenchi di pagine come Standby, Modified, Free e Zeroed
- Paged Pool / Nonpaged Pool del kernel
- Memoria tenuta dai driver di dispositivo
- Lo store di compressione della memoria
- Regioni condivise con o riservate per la GPU e altri dispositivi
- Memoria riservata dall’hardware
7.1. Available include anche cache riutilizzabile
Available MBytes di Windows non è semplicemente RAM del tutto inutilizzata. È un indicatore che, insieme a Free e Zeroed, include anche le pagine Standby che si possono riutilizzare se serve.12
- Free: pagine non attualmente allocate a nessuno scopo
- Zeroed: pagine azzerate così da poterle consegnare in sicurezza a un altro processo
- Standby: pagine che hanno lasciato un Working Set ma il cui contenuto è ancora in cache in RAM
- Modified: pagine il cui contenuto è cambiato e che vanno scritte sulla copertura appropriata prima del riuso
flowchart TB
accTitle: Movimento tra Working Set ed elenchi di pagine
accDescr: Mostra le pagine invariate che escono verso Standby e le modificate verso Modified, poi riaccesso, riscrittura e riuso
workingSet["Working Set - in uso"]
workingSet -->|rimossa pagina invariata| standby["Standby - candidata al riuso con contenuto tenuto"]
workingSet -->|rimossa pagina modificata| modified["Modified - in attesa di scrittura"]
modified -->|scrittura completata| standby
standby -->|riaccesso| workingSet
standby -->|riusata per un altro scopo| reused["Allocata a un altro scopo"]
free["Free - inutilizzata"] -->|azzerata| zeroed["Zeroed - disponibile per nuova allocazione"]
zeroed -->|accesso dopo l'allocazione| workingSet
standby -.-> available["Inclusa in Available"]
free -.-> available
zeroed -.-> available
Figura 8: Available include non solo la memoria del tutto libera ma anche Standby, che si può riutilizzare se serve.
«Scartare tutta la cache per aumentare la RAM libera» non è sempre un vantaggio. Se i dati di cui avete bisogno sono ancora in Standby, riaccedervi può riportarli nel Working Set in fretta senza leggere dal disco.
Quindi anche se Free è basso in Gestione attività, se Available è ampio e i hard page fault o le attese disco non stanno causando problemi, Windows può semplicemente stare usando la RAM in modo efficace come cache.
7.2. Quando la RAM si riduce senza un processo grande
Non è raro che il consumo di memoria resti inspiegato anche dopo aver sommato il Private Working Set di ogni processo.
- Cache dei file e file mappati in memoria
- Nonpaged Pool / Paged Pool
- Pagine bloccate da un driver
- Pagine condivise
- Compressione della memoria
- Allocazioni legate alla virtualizzazione o alla GPU
In questo caso, invece di continuare a fissare l’elenco dei processi, controllate Use Counts, Processes, Priority Summary e File Summary in RAMMap di Sysinternals. RAMMap è lo strumento ufficiale per scomporre la memoria fisica per scopo, elenco di pagine e file.13
Se cresce solo il Nonpaged Pool, quello è il punto in cui sospettare una perdita dal lato driver o kernel, piuttosto che nei Private Bytes di un’app in modalità utente.
8. Page Fault — un conteggio alto non è di per sé anomalo
Un Page Fault avviene quando un processo accede a una pagina che non è attualmente nel suo Working Set. Nonostante la parola «Fault» nel nome, non è un fallimento eccezionale — è il meccanismo normale che fa funzionare la memoria virtuale.1
8.1. Soft page fault
Si risolvono senza leggere dal disco.
- La pagina è ancora in Standby o Transition
- La stessa pagina condivisa è già nel Working Set di un altro processo
- Si accede per la prima volta a una pagina committed e viene assegnata una pagina a zero
- Il read-ahead del gestore della memoria l’ha già portata in RAM
Per questo un \Memory\Page Faults/sec grande non significa necessariamente che stia avvenendo I/O su disco o latenza.
8.2. Hard page fault
Richiedono di leggere il contenuto da un backing store su disco. La fonte non è limitata al file di paging.
- Codice e dati in un
.exeo.dll - Un file mappato in memoria
- Il file di paging
flowchart TB
accTitle: Il ramo tra soft e hard page fault
accDescr: Accedendo a una pagina non nel Working Set, si gestisce come soft page fault se l'I/O di storage non serve, o come hard page fault se serve
access["Accesso a una pagina non nel Working Set"] --> storageIo{"Serve I/O di storage"}
storageIo -->|No - Standby, condivisa, demand-zero, ecc.| soft["Soft page fault"]
soft --> resident["Entra nel Working Set senza leggere il disco"]
storageIo -->|Sì| hard["Hard page fault"]
hard --> source{"Da dove si legge"}
source --> image["EXE / DLL"]
source --> mapped["File mappato in memoria"]
source --> pagefile["File di paging"]
image --> loaded["Entra nel Working Set dopo il caricamento"]
mapped --> loaded
pagefile --> loaded
Figura 9: Il nome «Page Fault» da solo non vi dice se è avvenuto I/O su disco.
Microsoft elenca \Memory\Pages/sec, \Memory\Page Reads/sec e \Memory\Pages Input/sec tra i contatori per misurare i hard fault. Poiché il fatto che siano alti non significa necessariamente poca memoria, correlateli con Available MBytes, la latenza disco e il tempo di risposta effettivo.6
8.3. Non impostate una sola soglia universale
Un valore fisso come «qualunque cosa sopra 1000 Page Faults/sec è anomala» cambia significato a seconda dello storage, della dimensione di pagina, del carico di lavoro e della località di accesso.
In pratica, allineate quanto segue sulla stessa linea temporale.
Memory\Available MBytesMemory\Pages Input/secMemory\Page Reads/sec- Latenza di lettura / Queue sul disco di destinazione
- Working Set e Private Bytes del processo di destinazione
- Tempo di elaborazione dell’app, timeout e reattività dell’interfaccia
Se Available scende nello stesso momento in cui sale il carico, Pages Input/sec e l’attesa disco salgono, e anche il tempo di elaborazione peggiora, avete basi per sospettare paging causato da pressione sulla memoria fisica.
9. Quale schermata o strumento controllare per che cosa
| Che cosa volete sapere | L’indicatore da controllare per primo | Strumenti principali |
|---|---|---|
| La quantità che il processo di destinazione ha ora in RAM | Working Set | Gestione attività, Process Explorer, Get-Process |
| La porzione privata di quella — RAM privata del processo | Private Working Set / Working Set - Private | Colonne Dettagli di Gestione attività, Process Explorer, PerfMon |
| La quantità di commit privata del processo di destinazione | Private Bytes / Commit Size | Process Explorer, PerfMon, VMMap, Get-Process |
| L’intervallo di indirizzi virtuale del processo | Virtual Bytes / Size | Process Explorer, VMMap, Get-Process |
| Il margine di commit complessivo del sistema | Committed Bytes / Commit Limit | Gestione attività [Prestazioni], PerfMon |
| Il margine di riuso della RAM fisica | Available MBytes | Gestione attività, PerfMon |
| La scomposizione di Standby, Modified e cache dei file | Elenco di pagine / scomposizione per scopo | RAMMap |
| Che cosa è cresciuto dentro Private Bytes | Heap / Private Data / Managed Heap, ecc. | VMMap, WinDbg, dump specifici del runtime |
| Paging che coinvolge il disco | Pages Input/sec, Page Reads/sec, latenza disco | PerfMon, WPR/WPA |
flowchart TB
accTitle: Scegliere uno strumento di indagine sulla memoria Windows
accDescr: Lo strumento da usare dipende dal fatto che il bersaglio sia un processo o l'intero sistema, un istante o una serie temporale, e se serva tracciare la ritenzione dentro un runtime
question["Che cosa volete isolare"]
question --> processScope{"Il bersaglio è un solo processo"}
processScope -->|sì| processTime{"Un istante o una serie temporale"}
processTime -->|scomposizione di un istante| vmmap["VMMap"]
processTime -->|serie temporale| perfmon["PerfMon / PowerShell"]
processScope -->|intero sistema| systemView{"Scomposizione della RAM fisica o una linea temporale"}
systemView -->|scomposizione della RAM fisica| rammap["RAMMap"]
systemView -->|linea temporale con CPU, I/O e attese| wpa["WPR / WPA"]
question --> runtime{"Serve tracciare la ritenzione dentro un runtime"}
runtime -->|heap .NET| dotnet["dotnet-dump / PerfView"]
runtime -->|heap nativo| native["WinDbg / Application Verifier"]
Figura 10: Decidere prima l’ambito e la linea temporale vi fa scegliere esattamente lo strumento che vi serve, né di più né di meno.
9.1. Gestione attività
In Gestione attività, guardate le schermate separatamente.
- [Processi] o [Dettagli]: famiglie Working Set e Commit Size dei singoli processi
- [Prestazioni] → [Memoria]: In use, Available, Committed, Cached, Paged pool, Non-paged pool a livello di sistema
Non giudicate dalla sola colonna chiamata «Memoria» — fate clic con il tasto destro sulle intestazioni delle colonne nella scheda [Dettagli] e aggiungete le colonne di cui avete bisogno, come Working Set, Peak Working Set e Commit Size. I nomi delle colonne variano un po’ a seconda della versione di Windows e della lingua di visualizzazione, quindi confermate che cosa significa davvero una colonna prima di registrarla.
9.2. Catturare una serie temporale con PowerShell
Se conoscete l’ID del processo di destinazione, potete catturare insieme le tendenze di Working Set, Private Bytes e Virtual Bytes con Get-Process.
param(
[Parameter(Mandatory)]
[int]$ProcessId,
[int]$IntervalSeconds = 5,
[int]$SampleCount = 60
)
$samples = for ($i = 0; $i -lt $SampleCount; $i++) {
$process = Get-Process -Id $ProcessId -ErrorAction Stop
[pscustomobject]@{
Timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
ProcessId = $process.Id
WorkingSetMB = [math]::Round($process.WorkingSet64 / 1MB, 1)
PrivateBytesMB = [math]::Round($process.PrivateMemorySize64 / 1MB, 1)
VirtualBytesMB = [math]::Round($process.VirtualMemorySize64 / 1MB, 1)
Handles = $process.HandleCount
Threads = $process.Threads.Count
}
Start-Sleep -Seconds $IntervalSeconds
}
$samples | Format-Table -AutoSize
$samples | Export-Csv .\memory-samples.csv -NoTypeInformation -Encoding utf8
Process.WorkingSet64 di .NET corrisponde al Working Set, PrivateMemorySize64 a Private Bytes e VirtualMemorySize64 a Virtual Bytes.141516
Per un’app con più istanze, tracciate per PID e non per nome. Per un monitoraggio di lungo periodo in cui un riavvio cambia il PID, progettate la raccolta in modo da registrare l’ora di avvio, il nome del servizio e simili, così da non scambiare il bersaglio.
9.3. Mettere sistema e processo sulla stessa linea temporale con PerfMon
Registrare almeno quanto segue insieme rende l’isolamento molto più facile.
\Process(<destinazione>)\ID Process
\Process(<destinazione>)\Working Set
\Process(<destinazione>)\Working Set - Private
\Process(<destinazione>)\Private Bytes
\Process(<destinazione>)\Virtual Bytes
\Memory\Available MBytes
\Memory\Committed Bytes
\Memory\Commit Limit
\Memory\Pages Input/sec
\Memory\Page Reads/sec
\Memory\Pool Nonpaged Bytes
\Memory\Pool Paged Bytes
Quando più processi condividono lo stesso nome, o avviene un riavvio durante il monitoraggio, il solo nome dell’istanza — Process(name) o Process(name#N) — non fissa il bersaglio. Registrate ID Process per ogni campione, e adottate solo l’istanza il cui valore coincide con il PID che state tracciando. Quando coprite un riavvio che cambia il PID, registrate a parte anche l’ora del cambio.
I nomi dei contatori di prestazioni di Windows possono essere localizzati a seconda della lingua di visualizzazione. Se specificare direttamente il nome inglese in PowerShell non lo trova, aggiungete il contatore tramite l’interfaccia grafica di PerfMon, o controllate i nomi nel vostro ambiente locale con Get-Counter -ListSet *.
9.4. Non confondete i ruoli di VMMap e RAMMap
- VMMap: scompone la memoria virtuale e il Working Set di un processo in Heap, Image, Mapped File, Private Data, Managed Heap e simili
- RAMMap: scompone la RAM fisica dell’intero sistema per scopo, elenco di pagine, processo e file
«Che cosa ha fatto crescere i Private Bytes di questo processo» è un lavoro per VMMap; «a che cosa serve la RAM che l’elenco dei processi non spiega» è un lavoro per RAMMap.1713
10. Leggere i sintomi dalle combinazioni di numeri
| Andamento osservato | Prima ipotesi | Che cosa controllare dopo |
|---|---|---|
| Working Set sale, Private Bytes stabile | Primo accesso a pagine esistenti, una DLL condivisa, un file mappato, cache dei file | Image / Mapped File di VMMap, Pages Input/sec |
| Private Bytes sale, Working Set stabile | Il Commit privato è cresciuto ma è non residente o è stato Trim-mato | Heap / Private Data / Managed Heap di VMMap |
| Entrambi salgono subito dopo l’avvio, poi si appiattiscono | JIT, cache, pool, riscaldamento dell’inizializzazione | Se cresce di nuovo sotto lo stesso carico aggiuntivo |
| Il pavimento di Private Bytes sale a ogni giro di carico | Una perdita, una cache senza tetto, o un allocatore che trattiene memoria dopo il rilascio | Snapshot VMMap prima e dopo, un dump dell’heap |
| Solo il Working Set scende di colpo e torna con l’attività | L’OS o l’app ha fatto Trim del Working Set | Private Bytes, Pages Input/sec, tempo di risposta |
| X in Committed X/Y si avvicina a Y | Pressione di commit a livello di sistema | Maggiori consumatori di Private Bytes, Paged/Nonpaged Pool, impostazioni del file di paging |
| Available è basso, Pages Input/sec e latenza disco sono alti | Pressione sulla RAM fisica e hard paging | Maggiori consumatori di Working Set, RAMMap, correlazione del carico |
| L’uso di RAM è alto ma non c’è un processo grande | Cache, pagine condivise, pool del kernel, driver, compressione, ecc. | RAMMap, Pool Nonpaged/Paged Bytes |
| C’è RAM libera, eppure fallisce solo l’app a 32 bit | Un tetto di spazio di indirizzi virtuale o frammentazione | Free/Reserved di VMMap, impostazione LAA dell’eseguibile |
| Private Bytes è alto ma non cresce ripetendo l’elaborazione | Un pool o una cache che forse tiene un high watermark | Il suo limite, il comportamento di riuso, la stabilità dopo il picco |
La cosa più importante di questa tabella è leggerla in combinazione, non da un solo valore.
11. Una procedura pratica per indagare una perdita di memoria
11.1. Prima decidete le condizioni di riproduzione e il punto stazionario
«Cresce in pochi giorni» da solo non si può confrontare.
- Quanto del riscaldamento post-avvio includere
- Di che cosa consiste un ciclo di operazione
- Quanti secondi attendere dopo un ciclo
- Quanti giri servono per raggiungere il tetto della cache
- Se si può usare lo stesso input per le build sana e problematica
Decidete tutto questo.
11.2. Registrate processo e sistema insieme
Come minimo, tenete registrato quanto segue con gli stessi timestamp.
- Working Set del bersaglio
- Private Bytes del bersaglio
- Virtual Bytes del bersaglio
- Committed Bytes / Commit Limit del sistema
- Available MBytes
- Pages Input/sec
- Conteggio handle, conteggio thread
- Numero di operazioni o elementi elaborati
Se i Private Bytes del processo sono stabili mentre il Commit del sistema continua a crescere, dovete allargare l’ambito ad altri processi, al kernel, ai driver e alle sezioni condivise.
11.3. Decidete prima quale «dimensione» sta crescendo
- Solo Working Set: pagine residenti, condivise o derivate da file, Trim e ricaricamento
- Private Bytes: commit privato del processo
- Solo Virtual Bytes: Reserve, mapping, frammentazione dello spazio di indirizzi
- Solo System Commit: inclusi altri processi e il lato kernel
- Nonpaged Pool: lato driver/kernel
- Handles / GDI / USER: perdite in risorse diverse dalla memoria
Saltare questo ordine e passare subito a prendere un dump significa leggere una montagna di informazioni puntando alla cosa sbagliata.
11.4. Passate alla scomposizione
- Processo nativo: VMMap, WinDbg, Application Verifier, tracciamento dell’heap
- .NET:
dotnet-counters,dotnet-gcdump,dotnet-dump, PerfView - A livello di sistema: RAMMap, PerfMon, WPR/WPA
- Pool del kernel: PoolMon, WinDbg
VMMap mostra la memoria virtuale committed di un processo, e il Working Set allocato a ciascuna sua parte, scomposto per tipo. Quanto riuscite a restringere la crescita di Private Bytes a Heap, Private Data, Managed Heap o Mapped File fa una grande differenza sul costo dell’indagine che segue.17
11.5. Dopo una correzione, confrontate la tendenza nelle stesse condizioni
Non basta che il valore di picco differisca prima e dopo la correzione. Se il valore di partenza differisce, il confronto si può facilmente capovolgere.
- Stesso stato di avvio
- Stesso input
- Stesso numero di operazioni
- Stesso tempo di attesa
- Stesso intervallo di campionamento
— e confrontate il valore di pavimento e la tendenza dopo ogni ciclo. Provare la correzione di una perdita non è «il massimo è diventato più piccolo», ma che la crescita ora converge anche quando si ripete lo stesso carico.
12. Riformulare i malintesi comuni
Malinteso 1: La memoria di Gestione attività è uguale alla quantità totale che un’app ha allocato
Riformulato: Controllate di quale colonna si tratta. Per la famiglia Working Set è la quantità attualmente residente in RAM; per la famiglia Commit Size è il commit privato di quel processo.
Malinteso 2: Private Bytes è uguale ai byte sul file di paging
Riformulato: Private Bytes è Commit Charge privato. È una quantità promessa logica che include sia le pagine ora in RAM sia le pagine che sarebbero coperte dal file di paging se e quando serve.
Malinteso 3: Commit X/Y è uguale a uso del file di paging / capacità del file di paging
Riformulato: X è il Commit Charge a livello di sistema, e Y è il Commit Limit. Il file di paging estende Y, ma X non si traduce direttamente in uso su disco.
Malinteso 4: Un Page Faults/sec alto significa che sta facendo swap su disco
Riformulato: Questo include anche i soft fault. Controllate Pages Input/sec, Page Reads/sec e la latenza disco per vedere se l’I/O su disco è davvero coinvolto.
Malinteso 5: Poca RAM libera significa che la memoria è insufficiente
Riformulato: Guardate Available, Standby, l’hard paging e il tempo di risposta. Riempire la RAM di cache riutilizzabile è normale.
Malinteso 6: Ridurre il Working Set significa aver sistemato una perdita di memoria
Riformulato: Potreste aver solo evinto pagine dalla RAM. Controllate se Private Bytes e ciò che è trattenuto dentro l’heap sono davvero diminuiti.
Malinteso 7: Un aumento di Private Bytes conferma una perdita
Riformulato: Si può giudicare solo dopo aver controllato se converge quando si ripete lo stesso carico di lavoro, quale tipo di memoria è cresciuto, e se è una cache rilasciabile.
13. Riepilogo
- L’«utilizzo della memoria» di Windows non è un solo numero. Pensate separatamente a spazio di indirizzi, commit, residenza in RAM e condivisibilità.
- Working Set sono le pagine ora in RAM, comprese sia Private sia Shared. Private Working Set sono le pagine residenti private del processo all’interno di quello.
- Private Bytes è il Commit Charge privato del processo; non è né la quantità ora in RAM né la quantità realmente scritta nel file di paging.
- Committed X/Y è Commit Charge / Commit Limit a livello di sistema. Il file di paging sostiene principalmente il Commit Limit, l’evizione delle pagine modificate e i dump di crash.
- Un indirizzo virtuale Reserved, una pagina Committed e una pagina che è stata realmente toccata ed è entrata nel Working Set sono stadi distinti.
- Un Page Fault è funzionamento normale, e un soft fault non legge dal disco. Anche i hard fault possono avvenire non solo dal file di paging ma da un EXE, una DLL o un file mappato.
- Una perdita di memoria si prova non dalla dimensione in un singolo istante, ma dal valore di pavimento e dalla tendenza dopo lo stesso carico, insieme alla scomposizione.
- Il percorso di base è: VMMap per la scomposizione di un singolo processo, RAMMap per la RAM fisica a livello di sistema, PerfMon per una serie temporale, e uno strumento di dump dedicato per ciò che avviene dentro un runtime.
La prossima volta che notate in Gestione attività che «la memoria sta crescendo», cominciate col chiedervi questo.
Ciò che sta crescendo è il Working Set, Private Bytes, Virtual Bytes o il System Commit?
Quella domanda da sola rende l’ingresso della vostra indagine considerevolmente più preciso.
Articoli correlati
- Distinguere il ritardo del GC da una perdita di memoria in .NET — Una procedura pratica per osservare, confrontare e dimostrare la crescita della memoria
- Process Explorer / Handle / VMMap in pratica — Inseguire blocchi, perdite e «file in uso» dallo stato di adesso
- Le trappole della memoria condivisa e le migliori pratiche operative
- Le profondità dell’I/O di Windows (parte 4) — Cache Manager: quando il vostro WriteFile arriva davvero sul disco?
- Indagine sugli arresti anomali a lungo termine di un’app per fotocamere industriali: la perdita dell’handle (parte 1)
Aree di consulenza correlate
KomuraSoft LLC gestisce indagini sulle cause radice che combinano PerfMon, VMMap, RAMMap, WinDbg e gli strumenti diagnostici .NET per la crescita di memoria delle app Windows, il degrado delle prestazioni dopo un funzionamento prolungato, OutOfMemory nei processi a 32 bit e le carenze di memoria che si verificano solo nell’ambiente di un cliente. Non ci fermiamo a un semplice «la memoria è alta» — isoliamo quale regione è cresciuta, attraverso quale operazione, perché, e da dove viene referenziata o trattenuta.
- Sviluppo di applicazioni Windows
- Analisi dei bug e delle cause
- Consulenza tecnica e revisione del progetto
- Contattaci
Riferimenti
-
Microsoft Learn, Working Set. Sul fatto che il Working Set di un processo sia l’insieme delle pagine attualmente residenti in memoria fisica, comprese le pagine condivise; sulla differenza tra soft e hard page fault; sulle pagine Transition; e sulla rimozione di pagine dal Working Set. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, PROCESS_MEMORY_COUNTERS_EX2 structure. Sulle definizioni di WorkingSetSize, PrivateWorkingSetSize, PrivateUsage e SharedCommitUsage, e sul fatto che sia PagefileUsage sia PrivateUsage rappresentino il Commit Charge del processo. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Introduction to page files. Sul fatto che il file di paging sostenga l’evizione delle pagine modificate, i dump di crash di sistema e l’estensione del System Commit Limit; sulle definizioni di System Commit Charge e Commit Limit; e su come si misurano tramite Gestione attività e i contatori di prestazioni. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Page State. Sugli stati Free, Reserved e Committed di una pagina virtuale, e sul fatto che le pagine Reserved non abbiano archivio fisico associato e siano inaccessibili. ↩ ↩2
-
Microsoft Learn, VirtualAlloc function. Sulla differenza tra MEM_RESERVE e MEM_COMMIT; sul fatto che il commit venga addebitato sulla memoria complessiva del sistema e sul file di paging; e sul fatto che la pagina fisica effettiva a volte non venga allocata fino al primo accesso. ↩ ↩2 ↩3
-
Microsoft Learn, How to determine the appropriate page file size for 64-bit versions of Windows. Sul fatto che la dimensione del file di paging dipenda dal picco di Commit Charge e dai requisiti del dump di crash; sul fatto che i hard page fault leggano non solo dal file di paging ma anche da EXE, DLL e file mappati in memoria; e sui contatori di prestazioni correlati. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Virtual Address Space. Sul fatto che ogni processo abbia il proprio spazio di indirizzi virtuale indipendente e la propria tabella delle pagine, e che un indirizzo virtuale non sia di per sé un indirizzo fisico. ↩
-
Microsoft Learn, Memory Limits for Windows and Windows Server Releases. Sul fatto che lo spazio di indirizzi virtuale in modalità utente di un processo a 32 bit sia di norma 2 GB, e diventi 2 GB o 4 GB su Windows a 64 bit a seconda di IMAGE_FILE_LARGE_ADDRESS_AWARE. ↩
-
Microsoft Learn, SetProcessWorkingSetSize function. Sul fatto che i valori minimo e massimo del Working Set non garantiscano la residenza; sulla possibilità di svuotare un Working Set; e sul fatto che impostazioni o operazioni eccessive possano degradare le prestazioni del sistema. ↩
-
Microsoft Learn, Memory Performance Information. Sulla corrispondenza tra i contatori di prestazioni di Windows, le API di gestione della memoria e la visualizzazione di Gestione attività, inclusi Working Set / Working Set - Private / Private Bytes dell’oggetto Process, e Committed Bytes / Commit Limit dell’oggetto System. ↩
-
Microsoft Learn, MapViewOfFile function. Sul fatto che
FILE_MAP_COPYrenda ogni pagina potenzialmente copy-on-write, così che il Commit Charge per l’intera vista venga riservato per essere coperto dal file di paging al momento del mapping. ↩ -
Microsoft Learn, Understanding Node Metrics and Properties in HPC Cluster Manager. Sul fatto che Available Physical Memory si calcoli come somma degli elenchi Zeroed, Free e Standby, e sul significato di ciascuno di quegli elenchi di pagine. ↩
-
Microsoft Sysinternals, RAMMap. Sull’analisi dell’uso della memoria fisica di Windows per scopo, elenco di pagine, processo, priorità, pagina fisica e file. ↩ ↩2
-
Microsoft Learn, Process.WorkingSet64 Property. Sul fatto che
WorkingSet64restituisca il Working Set del processo in byte, corrispondente al contatore di prestazioni Working Set dell’oggetto Process. ↩ -
Microsoft Learn, Process.PrivateMemorySize64 Property. Sul fatto che
PrivateMemorySize64restituisca la memoria privata del processo che non si può condividere con altri processi, corrispondente al contatore di prestazioni Private Bytes. ↩ -
Microsoft Learn, Process.VirtualMemorySize64 Property. Sul fatto che
VirtualMemorySize64restituisca la quantità di memoria virtuale allocata per il processo, corrispondente al contatore di prestazioni Virtual Bytes. ↩ -
Microsoft Sysinternals, VMMap. Sulla scomposizione per tipo della memoria virtuale committed di un processo, e sulla visualizzazione della memoria fisica(Working Set)allocata a ciascuna, insieme a una mappa di memoria dettagliata. ↩ ↩2
Articoli correlati
Articoli recenti con gli stessi tag per approfondire argomenti vicini.
Le profondità della memoria di Windows (parte 2) — La vita di una pagina fisica: cinque elenchi e la verità sul file di paging
Questo articolo collega il database PFN, Standby, Modified, la compressione della memoria e il file di paging per spiegare dove va una pa...
App che si rompono alla ripresa dalla sospensione — Come funzionano gli eventi di alimentazione di Windows e come costruire app aziendali che li sopravvivono
Aprite il portatile e le connessioni dell'app aziendale sono morte — la causa è un progetto che non ha mai tenuto conto della sospensione...
DllMain e il loader lock — Il vero motivo per cui vi dicono di «non fare niente nell'inizializzazione della DLL»
Perché non dovete chiamare LoadLibrary o sincronizzarvi con altri thread da DllMain. A partire dalle fonti primarie, l'articolo spiega co...
Che cos'è davvero «Non risponde» — Come Windows decide che un'app è bloccata, e come progettare app che non lo sono
Il «Non risponde» di Windows è un meccanismo in cui il sistema operativo giudica che una finestra non ha prelevato un messaggio per 5 sec...
WPR/WPA in pratica — Introduzione all'indagine delle prestazioni a livello di sistema per «tutto il PC è lento»
I problemi di prestazioni come «tutto il PC è lento» o «l'avvio è lento» che il Task Manager non riesce a seguire si indagano catturando ...
Argomenti correlati
Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.
Argomenti tecnici Windows
Portale su sviluppo Windows, analisi dei problemi e valorizzazione delle risorse esistenti.
Servizi collegati all’argomento
L’articolo è direttamente collegato ai servizi seguenti.
Sviluppo di applicazioni Windows
Applicazioni aziendali, integrazione di dispositivi e strumenti di comunicazione, dai requisiti allo sviluppo.
Domande frequenti
Domande che ricorrono nelle consulenze sull’argomento dell’articolo.
- La colonna «Memoria» di Gestione attività mostra tutta la memoria che un'app ha allocato?
- No. Gestione attività ha diverse colonne di memoria — la famiglia Working Set, la famiglia Private Working Set, Commit Size e altre — e il significato dipende da quale schermata e colonna state guardando. Working Set sono le pagine attualmente residenti in RAM; Private Bytes o Commit Size è la quantità di commit propria di quel processo. Non leggete una singola colonna «Memoria» come la capacità totale che un'app ha allocato, né come la dimensione di una perdita.
- Qual è la differenza tra Working Set e Private Bytes?
- Working Set è la quantità di pagine visibili a quel processo e attualmente residenti nella RAM fisica, comprese le pagine condivisibili come il codice delle DLL e i file mappati in memoria. Private Bytes è la quantità di memoria committed usata esclusivamente da quel processo, indipendentemente dal fatto che sia attualmente residente in RAM. Le due quindi non coincidono mai, e nessuna delle due è sistematicamente maggiore dell'altra.
- «Committed 18/32GB» in Gestione attività significa che 18 GB sono stati scritti nel file di paging?
- No. La cifra di sinistra è il commit totale che l'intero sistema sta attualmente promettendo di coprire; quella di destra è il tetto di commit che il sistema può sostenere. Il tetto è determinato grosso modo da RAM più file di paging, ma non tutto il totale di sinistra sta davvero nel file di paging. La maggior parte delle pagine committed è in RAM, e ad alcune pagine committed non è mai stata assegnata una pagina fisica. Intanto le pagine che si possono ricaricare dal file originale — come EXE, DLL e file mappati in memoria — non alzano necessariamente il Commit privato della stessa quantità con cui alzano il Working Set.
- Si può ottenere OutOfMemory anche quando c'è RAM libera?
- Sì. L'allocazione può fallire per ragioni diverse dalla RAM fisica, tra cui un processo a 32 bit che esaurisce lo spazio di indirizzi virtuale, la mancanza di un intervallo di indirizzi liberi contiguo, il tetto di commit del sistema, o limiti propri di un Job Object o del runtime. In particolare, un processo a 32 bit su Windows a 64 bit è di norma limitato a 2 GB di spazio di indirizzi virtuale in modalità utente, a meno che non sia Large Address Aware.
- Disabilitare il file di paging rende Windows più veloce?
- Non si può assumerlo come regola generale. Disabilitare il file di paging abbassa il tetto di commit del sistema, rende più difficile evincere dalla RAM le pagine modificate inutilizzate e influisce su come si possono configurare i dump di crash. La dimensione del file di paging va decisa misurando il picco di commit charge e il dump di crash di cui avete bisogno — non è un'impostazione da disabilitare senza giustificazione.
- Un Page Faults/sec alto significa che il sistema è a corto di memoria?
- Da solo non si può dirlo. I page fault includono i soft fault, che si risolvono da pagine Standby in RAM o da pagine condivise con un altro processo, e i hard fault, che leggono dal disco. Invece di guardare Page Faults/sec isolato, controllate Pages Input/sec, Page Reads/sec, Available MBytes, la latenza disco e il tempo di elaborazione insieme sulla stessa linea temporale.
Profilo dell’autore
Pagina di presentazione dell’autore dell’articolo.
Go Komura
Rappresentante di KomuraSoft LLC
Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.