Cosa sono i byte privati, i byte virtuali, il working set?

Sto cercando di utilizzare l’utilità Perfmon Windows per eseguire il debug delle perdite di memoria in un processo.

Questo è il modo in cui perfmon spiega i termini:

Working Set è la dimensione corrente, in byte, del working set di questo processo. Il working set è l’insieme di pagine di memoria toccate di recente dai thread nel processo. Se la memoria disponibile nel computer supera una soglia, le pagine vengono lasciate nel working set di un processo anche se non sono in uso. Quando la memoria libera scende al di sotto di una soglia, le pagine vengono tagliate dai working set. Se necessario, verranno reindirizzati di nuovo nel set di lavoro prima di lasciare la memoria principale.

Byte virtuali è la dimensione corrente, in byte, dello spazio degli indirizzi virtuali utilizzato dal processo. L’uso dello spazio degli indirizzi virtuali non implica necessariamente l’uso corrispondente del disco o delle pagine di memoria principale. Lo spazio virtuale è finito e il processo può limitare la sua capacità di caricare le librerie.

Byte privati è la dimensione corrente, in byte, della memoria allocata da questo processo che non può essere condivisa con altri processi.

Queste sono le domande che ho:

Sono i Byte privati ​​che dovrei misurare per essere sicuri che il processo stia avendo delle perdite in quanto non comporta alcuna libreria condivisa e qualsiasi perdita, se accade, verrà dal processo stesso?

Qual è la memoria totale consumata dal processo? È il byte virtuale o è la sum di byte virtuali e set di lavoro?

Esiste una relazione tra byte privati, set di lavoro e byte virtuali?

Ci sono altri strumenti che danno un’idea migliore dell’uso della memoria?

La risposta breve a questa domanda è che nessuno di questi valori è un indicatore affidabile della quantità di memoria effettivamente utilizzata da un eseguibile e nessuno di questi è veramente appropriato per il debug di una perdita di memoria.

I Byte privati ​​si riferiscono alla quantità di memoria richiesta dall’eseguibile del processo, non necessariamente alla quantità effettivamente utilizzata . Sono “privati” perché (di solito) escludono i file mappati in memoria (cioè le DLL condivise). Ma – ecco il trucco – non necessariamente escludono la memoria allocata da quei file . Non è ansible stabilire se una modifica dei byte privati ​​sia dovuta all’eseguibile stesso o a una libreria collegata. Anche i byte privati non sono esclusivamente memoria fisica; possono essere cercati su disco o nell’elenco delle pagine di attesa (ovvero non più in uso, ma non ancora pagati).

Working Set si riferisce alla memoria fisica totale (RAM) utilizzata dal processo. Tuttavia, a differenza dei byte privati, questo include anche i file mappati in memoria e varie altre risorse, quindi è una misurazione ancora meno accurata dei byte privati. Questo è lo stesso valore che viene riportato in “Mem Usage” di Task Manager ed è stato fonte di una quantità infinita di confusione negli ultimi anni. La memoria nel working set è “fisica” nel senso che può essere indirizzata senza un errore di pagina; tuttavia, anche l’elenco delle pagine in standby è ancora fisicamente in memoria ma non è riportato nel working set, e questo è il motivo per cui si potrebbe vedere improvvisamente cadere “Mem Usage” quando si minimizza un’applicazione.

Byte virtuali sono lo spazio di indirizzo virtuale totale occupato dall’intero processo. Questo è come il working set, nel senso che include file mappati in memoria (DLL condivise), ma include anche i dati nell’elenco di standby e i dati che sono già stati sfogliati e si trova in un file di paging su disco da qualche parte. I byte virtuali totali utilizzati da ogni processo su un sistema sottoposto a un carico elevato sumno una quantità di memoria significativamente maggiore rispetto a quella effettiva della macchina.

Quindi le relazioni sono:

  • Byte privati ​​sono ciò che l’app ha effettivamente assegnato, ma includono l’utilizzo del file di paging;
  • Working Set sono i byte privati ​​non di paging più i file mappati in memoria;
  • Byte virtuali sono il working set più i byte privati ​​paginati e l’elenco standby.

C’è un altro problema qui; proprio come le librerie condivise possono allocare memoria all’interno del modulo dell’applicazione, portando a potenziali falsi positivi riportati nei Byte privati ​​della tua app, la tua applicazione potrebbe anche finire per allocare memoria all’interno dei moduli condivisi , portando a falsi negativi . Ciò significa che è effettivamente ansible che l’applicazione abbia una perdita di memoria che non si manifesta mai nei Byte privati. Improbabile, ma ansible.

I Byte privati ​​rappresentano un’approssimazione ragionevole della quantità di memoria utilizzata dall’eseguibile e possono essere utilizzati per limitare una lista di potenziali candidati per una perdita di memoria; se vedi il numero crescere e crescere costantemente e all’infinito, vorrai controllare quel processo per trovare una perdita. Tuttavia, ciò non può dimostrare che ci sia o meno una perdita.

Uno degli strumenti più efficaci per rilevare / correggere perdite di memoria in Windows è in realtà Visual Studio (il collegamento va alla pagina sull’utilizzo di VS per perdite di memoria, non sulla pagina del prodotto). Rational Purify è un’altra possibilità. Microsoft ha anche un documento di best practice più generale su questo argomento. Ci sono più strumenti elencati in questa domanda precedente .

Spero che questo chiarisca alcune cose! Tenere traccia delle perdite di memoria è una delle cose più difficili da fare nel debug. In bocca al lupo.

Non dovresti provare a usare perfmon, task manager o qualsiasi strumento del genere per determinare perdite di memoria. Sono buoni per identificare le tendenze, ma non molto altro. I numeri riportati in termini assoluti sono troppo vaghi e aggregati per essere utili per un’attività specifica come il rilevamento di perdite di memoria.

Una precedente risposta a questa domanda ha dato una grande spiegazione di ciò che i vari tipi sono.

Chiedete un consiglio sugli strumenti: raccomando Memoria Validatore. In grado di monitorare applicazioni che generano miliardi di allocazioni di memoria.

http://www.softwareverify.com/cpp/memory/index.html

Dichiarazione di non responsabilità: ho progettato il Validatore della memoria.

La definizione dei contatori perfmon è stata interrotta sin dall’inizio e per qualche motivo sembra essere troppo difficile da correggere.

Una buona panoramica della gestione della memoria di Windows è disponibile nel video ” Mysteries of Memory Management Revealed ” su MSDN: copre più argomenti del necessario per tenere traccia delle perdite di memoria (ad esempio la gestione dei set di lavoro) ma fornisce dettagli sufficienti negli argomenti rilevanti.


Per darti un’idea del problema con le descrizioni del contatore dei perfmon, ecco la storia interna dei byte privati ​​di ” Contatore prestazioni byte privati ​​- Attenzione! ” Su MSDN:

D: Quando un Byte privato non è un Byte privato?

A: Quando non è residente.

Il contatore Byte privati ​​riporta l’addebito di commit del processo. Vale a dire, la quantità di spazio che è stato allocato nel file di scambio per contenere il contenuto della memoria privata nel caso in cui venga scambiato. Nota: evito la parola “riservato” a causa di una ansible confusione con la memoria virtuale nello stato riservato che non è stato eseguito.


Da ” Pianificazione delle prestazioni ” su MSDN:

3.3 Byte privati

3.3.1 Descrizione

La memoria privata è definita come memoria allocata per un processo che non può essere condiviso da altri processi. Questa memoria è più costosa della memoria condivisa quando più processi di questo tipo vengono eseguiti su una macchina. La memoria privata in DLL (tradizionali) non gestite di solito costituisce una statistica C ++ ed è dell’ordine del 5% del set di lavoro totale della DLL.

C’è una discussione interessante qui: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ La mia comprensione di questa discussione è che la liberazione di piccole allocazioni è non riflessa in Byte privati ​​o Set di lavoro.

Per farla breve:

se chiamo

p=malloc(1000); free(p); 

quindi i Byte privati ​​riflettono solo l’allocazione, non la deallocazione.

se chiamo

 p=malloc(>512k); free(p); 

quindi i Byte privati ​​riflettono correttamente l’allocazione e la deallocazione.