Domanda

Sto cercando di scoprire quanta memoria utilizza il mio processo server .Net (per scopi di monitoraggio e registrazione).

Sto usando:

Process.GetCurrentProcess().PrivateMemorySize64

Tuttavia, l'oggetto Process ha diverse proprietà che mi consentono di leggere lo spazio di memoria utilizzato:Paged, NonPaged, PagedSystem, NonPagedSystem, Privato, Virtuale, WorkingSet

e poi le "picchi":che immagino memorizzi solo i valori massimi che questi ultimi abbiano mai assunto.

Leggere la definizione MSDN di ciascuna proprietà non si è rivelato molto utile per me.Devo ammettere che la mia conoscenza su come viene gestita la memoria (per quanto riguarda il paging e il virtuale) è molto limitata.

Quindi la mia domanda è ovviamente "quale dovrei usare?", e so che la risposta è "dipende".

Questo processo manterrà fondamentalmente un mucchio di elenchi in memoria di cose che stanno accadendo, mentre altri processi comunicano con esso e lo interrogano per informazioni.Mi aspetto che il server su cui verrà eseguito richieda molta RAM, quindi sto interrogando questi dati nel tempo per poter stimare i requisiti di RAM rispetto alle dimensioni degli elenchi che mantiene all'interno.

COSÌ...Quale dovrei usare e perché?

È stato utile?

Soluzione

Se vuoi sapere quanto utilizza il GC prova:

GC.GetTotalMemory(true)

Se vuoi sapere cosa utilizza il tuo processo da Windows (colonna Dimensioni VM in TaskManager) prova:

Process.GetCurrentProcess().PrivateMemorySize64

Se vuoi sapere cosa ha il tuo processo nella RAM (invece che nel file di paging) (colonna Utilizzo mem in TaskManager) prova:

Process.GetCurrentProcess().WorkingSet64

Vedere Qui per ulteriori spiegazioni sui diversi tipi di memoria.

Altri suggerimenti

OK, ho trovato tramite Google la stessa pagina menzionata da Lars e credo che sia un'ottima spiegazione per le persone che non sanno bene come funziona la memoria (come me).

http://shsc.info/WindowsMemoryManagement

La mia breve conclusione è stata:

  • Byte privati ​​= La memoria che il mio processo ha richiesto per archiviare i dati.Alcuni di essi potrebbero essere paginati su disco o meno.Queste sono le informazioni che cercavo.

  • Byte virtuali = I byte privati, più lo spazio condiviso con altri processi per le DLL caricate, ecc.

  • Working Set = La parte di TUTTA la memoria del mio processo che non è stata paginata su disco.Pertanto la quantità di pagine su disco dovrebbe essere (Virtual - Working Set).

Grazie a tutti per il vostro aiuto!

Se si desidera utilizzare "Memoria (Private Working Set)" come mostrato nel task manager di Windows Vista, che è l'equivalente di Process Explorer "WS Private Bytes", ecco il codice.Probabilmente è meglio lanciare questo ciclo infinito in un thread/attività in background per statistiche in tempo reale.

using System.Threading;
using System.Diagnostics;

//namespace...class...method

Process thisProc = Process.GetCurrentProcess();
PerformanceCounter PC = new PerformanceCounter();

PC.CategoryName = "Process";
PC.CounterName = "Working Set - Private";
PC.InstanceName = thisProc.ProcessName;

while (true)
{
 String privMemory = (PC.NextValue()/1000).ToString()+"KB (Private Bytes)";
 //Do something with string privMemory

 Thread.Sleep(1000);
}

Per ottenere il valore offerto da Task Manager, tanto di cappello alla soluzione di Mike Regan sopra.Tuttavia, una modifica:non è: perfCounter.NextValue()/1000; Ma perfCounter.NextValue()/1024; (cioè.un kilobyte reale).Questo dà il valore esatto che vedi in Task Manager.

Di seguito è riportata una soluzione completa per visualizzare l'utilizzo della memoria (quello del Task Manager, come indicato) in modo semplice nell'app WPF o WinForms (in questo caso, semplicemente nel titolo).Basta chiamare questo metodo all'interno del nuovo costruttore Window:

    private void DisplayMemoryUsageInTitleAsync()
    {
        origWindowTitle = this.Title; // set WinForms or WPF Window Title to field
        BackgroundWorker wrkr = new BackgroundWorker();
        wrkr.WorkerReportsProgress = true;

        wrkr.DoWork += (object sender, DoWorkEventArgs e) => {
            Process currProcess = Process.GetCurrentProcess();
            PerformanceCounter perfCntr = new PerformanceCounter();
            perfCntr.CategoryName = "Process";
            perfCntr.CounterName = "Working Set - Private";
            perfCntr.InstanceName = currProcess.ProcessName;

            while (true)
            {
                int value = (int)perfCntr.NextValue() / 1024;
                string privateMemoryStr = value.ToString("n0") + "KB [Private Bytes]";
                wrkr.ReportProgress(0, privateMemoryStr);
                Thread.Sleep(1000);
            }
        };

        wrkr.ProgressChanged += (object sender, ProgressChangedEventArgs e) => {
            string val = e.UserState as string;
            if (!string.IsNullOrEmpty(val))
                this.Title = string.Format(@"{0}   ({1})", origWindowTitle, val);
        };

        wrkr.RunWorkerAsync();
    }`

Il working set non è una buona proprietà da usare.Da quello che ho capito, include tutto ciò che il processo può toccare, anche le librerie condivise da più processi, quindi in quel contatore vedi byte conteggiati due volte.La memoria privata è un contatore molto migliore da guardare.

Suggerirei di monitorare anche la frequenza con cui si verificano i pagefault.Si verifica un pagefault quando si tenta di accedere ad alcuni dati che sono stati spostati dalla memoria fisica al file di scambio e il sistema deve leggere la pagina dal disco prima di poter accedere a questi dati.

È una descrizione corretta?Vorrei condividerlo con il mio team, quindi per favore fatemi sapere se non è corretto (o è incompleto):

In C# sono disponibili diversi modi per chiedere la quantità di memoria utilizzata dal processo.

  • La memoria allocata può essere gestita (da CLR) o non gestita.
  • La memoria allocata può essere virtuale (archiviata su disco) o caricata (nelle pagine RAM)
  • La memoria allocata può essere privata (utilizzata solo dal processo) o condivisa (ad es.appartenente a una DLL a cui fanno riferimento altri processi).

Considerato quanto sopra, ecco alcuni modi per misurare l'utilizzo della memoria in C#:

1) Process.VirtualMemorySize64():restituisce tutta la memoria utilizzata da un processo: gestito o non gestito, virtuale o caricato, privato o condiviso.

2) Process.PrivateMemorySize64():restituisce tutta la memoria privata utilizzata da un processo: gestito o non gestito, virtuale o caricato.

3) Processo.WorkingSet64():restituisce tutta la memoria privata caricata utilizzata da un processo, gestito o non gestito

4) GC.GetTotalMemory():restituisce la quantità di memoria gestita controllata dal Garbage Collector.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top