Pregunta

Estoy tratando de averiguar cuánta memoria está utilizando mi propio proceso de servidor .Net (para fines de monitoreo y registro).

Estoy usando:

Process.GetCurrentProcess().PrivateMemorySize64

Sin embargo, el objeto Proceso tiene varias propiedades diferentes que me permiten leer el espacio de memoria utilizado:paginado, no paginado, sistema paginado, sistema no paginado, privado, virtual, conjunto de trabajo

y luego los "picos":Supongo que solo almacena los valores máximos que tomaron estos últimos.

Leer la definición de MSDN de cada propiedad no me ha resultado muy útil.Debo admitir que mi conocimiento sobre cómo se administra la memoria (en lo que respecta a paginación y virtual) es muy limitado.

Entonces mi pregunta es obviamente "¿cuál debo usar?", Y sé que la respuesta es "depende".

Este proceso básicamente mantendrá un montón de listas en la memoria de las cosas que están sucediendo, mientras que otros procesos se comunican con él y le consultan cosas.Espero que el servidor donde se ejecutará esto requiera mucha RAM, por lo que estoy consultando estos datos a lo largo del tiempo para poder estimar los requisitos de RAM en comparación con los tamaños de las listas que mantiene dentro.

Entonces...¿Cuál debo usar y por qué?

¿Fue útil?

Solución

Si quieres saber cuánto usa el GC, prueba:

GC.GetTotalMemory(true)

Si desea saber qué utiliza su proceso desde Windows (columna Tamaño de VM en TaskManager), intente:

Process.GetCurrentProcess().PrivateMemorySize64

Si desea saber qué tiene su proceso en la RAM (a diferencia del archivo de paginación) (columna Uso de memoria en el Administrador de tareas), intente:

Process.GetCurrentProcess().WorkingSet64

Ver aquí para obtener más explicaciones sobre los diferentes tipos de memoria.

Otros consejos

OK, encontré a través de Google la misma página que mencionó Lars, y creo que es una gran explicación para las personas que no saben muy bien cómo funciona la memoria (como yo).

http://shsc.info/WindowsMemoryManagement

Mi breve conclusión fue:

  • Bytes privados = La memoria que mi proceso ha solicitado para almacenar datos.Parte de él puede paginarse en el disco o no.Esta es la información que estaba buscando.

  • Bytes virtuales = Los bytes privados, más el espacio compartido con otros procesos para las DLL cargadas, etc.

  • Conjunto de trabajo = La porción de TODA la memoria de mi proceso que no ha sido paginada en el disco.Por lo tanto, la cantidad paginada en el disco debe ser (Virtual - Conjunto de trabajo).

¡Gracias a todos por su ayuda!

Si desea utilizar la "Memoria (conjunto de trabajo privado)" como se muestra en el administrador de tareas de Windows Vista, que es el equivalente de "WS Private Bytes" de Process Explorer, aquí está el código.Probablemente sea mejor lanzar este bucle infinito en un hilo/tarea en segundo plano para obtener estadísticas en tiempo real.

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);
}

Para obtener el valor que ofrece el Administrador de tareas, me quito el sombrero ante la solución anterior de Mike Regan.Sin embargo, un cambio:No lo es: perfCounter.NextValue()/1000; pero perfCounter.NextValue()/1024; (es decir.un kilobyte real).Esto proporciona el valor exacto que ve en el Administrador de tareas.

A continuación se muestra una solución completa para mostrar el 'uso de memoria' (administrador de tareas, como se indica) de una manera sencilla en su aplicación WPF o WinForms (en este caso, simplemente en el título).Simplemente llame a este método dentro del nuevo constructor de Windows:

    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();
    }`

El conjunto de trabajo no es una buena propiedad para usar.Por lo que deduzco, incluye todo lo que el proceso puede tocar, incluso bibliotecas compartidas por varios procesos, por lo que estás viendo bytes contados dos veces en ese contador.La memoria privada es un contador mucho mejor a la vista.

Sugeriría controlar también la frecuencia con la que ocurren errores de página.Se produce un error de página cuando intenta acceder a algunos datos que se han movido de la memoria física a un archivo de intercambio y el sistema tiene que leer la página del disco antes de poder acceder a estos datos.

¿Es esta una descripción justa?Me gustaría compartir esto con mi equipo, así que avísenme si es incorrecto (o está incompleto):

Hay varias formas en C# de preguntar cuánta memoria está usando mi proceso.

  • La memoria asignada puede ser administrada (por CLR) o no administrada.
  • La memoria asignada puede ser virtual (almacenada en disco) o cargada (en páginas RAM)
  • La memoria asignada puede ser privada (utilizada sólo por el proceso) o compartida (p. ej.perteneciente a una DLL a la que otros procesos hacen referencia).

Teniendo en cuenta lo anterior, aquí hay algunas formas de medir el uso de memoria en C#:

1) Proceso.VirtualMemorySize64():devuelve toda la memoria utilizada por un proceso: administrada o no administrada, virtual o cargada, privada o compartida.

2) Proceso.PrivateMemorySize64():devuelve toda la memoria privada utilizada por un proceso: administrada o no administrada, virtual o cargada.

3) Proceso.WorkingSet64():devuelve toda la memoria privada cargada utilizada por un proceso, administrada o no administrada

4) GC.GetTotalMemory():devuelve la cantidad de memoria administrada que supervisa el recolector de basura.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top