2015-10-08 34 views
6

Sto utilizzando VMMap per analizzare l'utilizzo dello spazio degli indirizzi di Virtual/Process nella mia modalità mista (gestita e non gestita). Capisco come funziona Windows VMM e Virtual Memory API, capisco come funziona anche l'Heap Memory API. Ho esaminato l'implementazione CRT che sto usando (non in modo molto dettagliato) e (penso che io - questo potrebbe essere il mio declino) capisco come questo usi le API Win32 di cui sopra.Cosa definisce "Dati privati" in VMMAP?

Sto cercando di capire cosa mi sta mostrando questa statistica "Dati personali". La mia applicazione non effettua chiamate dirette a nessuna delle funzioni dell'API della memoria di Win32, utilizza sempre solo "malloc/new" in C++ nativo e "nuova" in C# (che in fondo utilizzerà l'API di gestione della memoria Win32).

La definizione di "Private Data" data dal VMMap è:

memoria privato memoria allocata da VirtualAlloc e non suballocated né dalla Heap Manager o il tempo di esecuzione di .NET. Lo non può essere condiviso con altri processi, viene addebitato sul limite di commit del sistema e in genere contiene dati dell'applicazione.

Quindi immagino che questa definizione mi faccia chiedere, ok, quindi chi sta facendo le chiamate a VirtualAlloc? È il gestore di heap o il tempo di esecuzione .Net?

Potrei ottenere un indirizzo di alcuni dei dati privati ​​impegnati e utilizzare WinDbg per scoprirlo .... Bene ... si scopre che Microsoft nella loro saggezza ha nobilitato i simboli pubblici ntdll, quindi WinDbg non funziona così bene - posso fornire maggiori dettagli su questo se richiesto, ma fondamentalmente comandi come! indirizzo -summary non funzionano più a causa di simboli mancanti.

Un altro modo per formulare questa domanda potrebbe: quale codice C + + o C# posso scrivere che farà aumentare o diminuire questa statistica di dati privati? O tutto questo è gestito dal sistema operativo, dal runtime C++ o dal runtime .Net e quindi alla mercé dei suoi capricci?

posso dedurre dalla natura del VMMap (altri tipi di memoria sono escludono a vicenda) che questo "dati privati", quindi non può essere uno qualsiasi dei seguenti tipi di spazio di indirizzamento:

  • Heap (nota che questo include lo spazio heap riservato e riservato - riservato tramite una chiamata a VirtualAlloc, come descritto nella descrizione dei dati privati ​​ sopra).
  • Managed Mucchio
  • Pila
  • file mappato
  • Condivisibile
  • Immagine
  • Page Table
  • inutilizzabile
  • libero

(non riuscivo a trovare un aiuto in linea file che definisce cosa pensa VMMap quanto sopra i tipi sono, ma ecco un link per scaricare il file della guida: https://technet.microsoft.com/en-us/library/dd535533.aspx)

Ho notato che nella mia applicazione, la dimensione TOTALE (riservata e impegnata) dei dati privati ​​rimane abbastanza costante per tutta la durata delle mie applicazioni, nonostante l'Heap/Dimensioni di heap/stack gestiti che cambiano come previsto.Ho anche notato che del totale di ~ 250Mb utilizzato dai dati privati, solo ~ 33Mb è effettivamente impegnato. Nota che il mio metodo di misurazione è piuttosto rudimentale, quindi il valore potrebbe cambiare tra ciascuna delle mie misurazioni e io non lo vedo (se sapessi che cosa stava misurando, potrei usare DebugDiag per catturare un dump del processo quando il contatore relativo ha colpito una certa soglia, pollo e uovo).

La mia teoria speculativa corrente è che questo è lo spazio che viene riservato per far crescere gli heap nativi (o gestiti supponiamo?) Nel momento in cui raggiungono la loro capacità, ma non ho nulla da dimostrare. Quindi rimane saldamente nella pila speculativa.

Cercare informazioni su Internet può essere doloroso, ci sono molti post/articoli/blog che confondono le cose, usano definizioni autoreferenziali (la prima frase della definizione di Performance Monitor per Working Set è un ottimo esempio di questo), sono incompleti o sono semplicemente sbagliati. Molti posti sfocano definizioni o usano una terminologia incoerente (si noti che la definizione VMMaps dei dati privati ​​del campo, continua a riferirsi ad essa come memoria privata, forse un po 'di lamentela anale, ma ambiguità).

Ora che ho criticato il resto di Internet per ottenere cose confuse e errate ... se c'è qualcosa di cui sopra che non ha senso o puoi mostrarmi la documentazione al contrario o hai bisogno di un definizione più esplicita di, fammi sapere e mi metto anche sulla lista dei criminali! Penso che la prima metà del tentativo di spiegare un problema di memoria a qualcuno, online, si stia assicurando che stiamo parlando della stessa cosa.

Infine questa domanda: How does VMMap know a given memory region is Thread Stack, specifically? suggerisce che non può mai scoprire una risposta:/

UPDATE/EDIT: ho scoperto che accendendo gflags stack utente tracciamento (gflags -i myapp.exe + ust), è può aumentare la dimensione dei Dati Privati, suppongo che questo sia il database backtrace, ma anche senza gflag, ci sono ancora Dati Privati ​​che non riesco a giustificare.

+0

Attualmente sto riscontrando un problema molto simile sulla mia applicazione che causa effettivamente OutOfMemoryException in un ambiente specifico. Sono riuscito a creare un codice C# in PInvoke VirtualAlloc manualmente (da kernel32.dll) e genera lo stesso risultato VMMap, allocando enormi blocchi di "Dati personali" (vedi [questo link] (http://mjs5.com/2016/ 04/06/c-allocare-fast-non gestito-memory-o-grandi blocchi-VirtualAlloc-allochglobal /)). Tuttavia sto ancora cercando di rintracciare da dove sono stati assegnati questi "dati personali". Sto provando a usare VMMap per tracciare quei dati, ma senza risultati fino ad ora. –

risposta

1

So che è una domanda piuttosto vecchia. Ma è ancora senza risposta per qualche motivo. Questa domanda è stata menzionata da Sasha Goldstein nel suo discorso su WinDbg alla conferenza DotNext - https://www.youtube.com/watch?v=8t1aTbnZ2CE. Il punto è che può essere facilmente risolto con l'aiuto di WinDbg.

Per sapere se CLR utilizza VirtualAlloc per il suo heap, imposteremo un punto di interruzione in questa funzione con uno script che stampa lo stack corrente (nativo e gestito).

bp kernelbase!VirtualAlloc ".printf \"allocating %d bytes of virtual memory\", dwo(@esp+8);.echo; k 5; !clrstack; gc" 

Qui: k 5 stampa ultimo 5 fotogrammi di stack nativo e !clrstack (da SOS) stampe gestite stack. gc continua l'esecuzione.

Si noti che questo script funzionerà solo per i processi x86. Per x64 avrai bisogno di altri (registri e convenzioni di chiamata differenti).

Quindi ho creato un programma semplice che assegna un oggetto e lo aggiunge a un elenco.

static void Main(string[] args) 
    { 
     var list = new List<string[]>(); 
     while (true) { 
      var a = Console.ReadLine(); 
      if (a == "q" || a == "Q") break; 
      var arr = new string[100]; 
      list.Add(arr); 
     } 
    } 

Eseguirlo in WinDbg e avviare premendo Invio. Ad un certo punto il punto di interruzione ha colpito - sulla lista in espansione e l'allocazione di memoria aggiuntiva nel mucchio:

enter image description here

Così, ovviamente CLR utilizza VirtualAlloc per l'allocazione di memoria per il suo mucchio.

+0

Grazie per la risposta. Una sorta di ovvia soluzione quando la guardo ora! Non ho intenzione di contrassegnarlo come la risposta in quanto fornisce solo più informazioni di supporto, ma in realtà non affronta "Cosa definisce" Dati privati ​​"in VMMAP?" –