¿Qué son los bytes privados, los bytes virtuales, el conjunto de trabajo?

Estoy tratando de usar la utilidad de Windows perfmon para depurar memory leaks en un proceso.

Así es como perfmon explica los términos:

Working Set es el tamaño actual, en bytes, del conjunto de trabajo de este proceso. El conjunto de trabajo es el conjunto de páginas de memoria tocadas recientemente por los hilos en el proceso. Si la memoria libre en la computadora está por encima de un umbral, las páginas se dejan en el conjunto de trabajo de un proceso, incluso si no están en uso. Cuando la memoria libre cae por debajo de un umbral, las páginas se recortan de Conjuntos de trabajo. Si se necesitan, se volverán a introducir fallas suaves en el conjunto de trabajo antes de abandonar la memoria principal.

Bytes virtuales es el tamaño actual, en bytes, del espacio de direcciones virtuales que utiliza el proceso. El uso del espacio de direcciones virtuales no implica necesariamente el uso correspondiente del disco o de las páginas de la memoria principal. El espacio virtual es finito y el proceso puede limitar su capacidad para cargar bibliotecas.

Bytes privados es el tamaño actual, en bytes, de la memoria que este proceso ha asignado y que no se puede compartir con otros procesos.

Estas son las preguntas que tengo:

¿Son los Bytes privados los que debería medir para estar seguro de si el proceso está teniendo alguna fuga, ya que no involucra ninguna biblioteca compartida y cualquier fuga, si ocurre, vendrá del proceso mismo?

¿Cuál es la memoria total consumida por el proceso? ¿Son los Bytes Virtuales o es la sum de Bytes Virtuales y Conjunto de Trabajo?

¿Hay alguna relación entre Bytes privados, Working Set y Bytes virtuales?

¿Hay alguna otra herramienta que brinde una mejor idea del uso de la memoria?

La respuesta breve a esta pregunta es que ninguno de estos valores es un indicador confiable de la cantidad de memoria que realmente está usando un ejecutable, y ninguno de ellos es realmente apropiado para depurar una pérdida de memoria.

Bytes privados se refieren a la cantidad de memoria que el proceso ejecutable ha pedido , no necesariamente la cantidad que realmente está usando . Son “privados” porque (por lo general) excluyen archivos mapeados en memoria (es decir, archivos DLL compartidos). Pero, aquí está el truco, no excluyen necesariamente la memoria asignada por esos archivos . No hay forma de saber si un cambio en los bytes privados se debió al ejecutable mismo o debido a una biblioteca vinculada. Los bytes privados tampoco son exclusivamente memoria física; se pueden localizar en el disco o en la lista de la página en espera (es decir, ya no están en uso, pero tampoco están paginados).

Working Set se refiere a la memoria física total (RAM) utilizada por el proceso. Sin embargo, a diferencia de los bytes privados, esto también incluye archivos mapeados en memoria y varios otros recursos, por lo que es una medida aún menos precisa que los bytes privados. Este es el mismo valor que se informa en “Uso de memoria” del Administrador de tareas y ha sido la fuente de una cantidad interminable de confusión en los últimos años. La memoria en el conjunto de trabajo es “física” en el sentido de que puede abordarse sin un error de página; sin embargo, la lista de la página en espera también está todavía físicamente en la memoria pero no se informa en el conjunto de trabajo, y es por esto que es posible que vea que el “uso de memoria” cae repentinamente cuando minimiza una aplicación.

Bytes virtuales son el espacio de dirección virtual total ocupado por todo el proceso. Esto es como el conjunto de trabajo, en el sentido de que incluye archivos mapeados en memoria (DLL compartidos), pero también incluye datos en la lista de espera y datos que ya han sido paginados y está ubicado en un archivo de paginación en algún lugar del disco. El total de bytes virtuales utilizados por cada proceso en un sistema bajo carga pesada agregará mucha más memoria que la que realmente tiene la máquina.

Entonces las relaciones son:

  • Los bytes privados son los que su aplicación realmente ha asignado, pero incluyen el uso del archivo de paginación;
  • El Conjunto de trabajo es los Bytes privados no paginados más los archivos mapeados en memoria;
  • Bytes virtuales son el conjunto de trabajo más Bytes privados paginados y la lista de espera.

Hay otro problema aquí; así como las bibliotecas compartidas pueden asignar memoria dentro de su módulo de aplicación, lo que puede generar falsos positivos potenciales en los Bytes privados de su aplicación, su aplicación también puede terminar asignando memoria dentro de los módulos compartidos , lo que lleva a falsos negativos . Eso significa que es posible que su aplicación tenga una pérdida de memoria que nunca se manifiesta en Bytes privados. Poco probable, pero posible.

Los Bytes privados son una aproximación razonable de la cantidad de memoria que está usando su ejecutable y se pueden usar para ayudar a reducir una lista de candidatos potenciales para una pérdida de memoria; si ve que el número crece y crece constantemente y sin parar, le conviene verificar el proceso para detectar una fuga. Esto no puede, sin embargo, probar que hay o no una fuga.

Una de las herramientas más efectivas para detectar / corregir memory leaks en Windows es en realidad Visual Studio (el enlace va a la página sobre el uso de VS para memory leaks, no la página del producto). Rational Purify es otra posibilidad. Microsoft también tiene un documento de mejores prácticas más general sobre este tema. Hay más herramientas enumeradas en esta pregunta anterior .

¡Espero que esto aclare algunas cosas! Rastrear memory leaks es una de las cosas más difíciles de hacer en la depuración. Buena suerte.

No debe intentar utilizar perfmon, el administrador de tareas o cualquier herramienta como esa para determinar pérdidas de memoria. Son buenos para identificar tendencias, pero no mucho más. Las cifras que informan en términos absolutos son demasiado vagas y agregadas para ser útiles para una tarea específica, como la detección de memory leaks.

Una respuesta anterior a esta pregunta ha proporcionado una gran explicación de cuáles son los diversos tipos.

Pregunta acerca de una recomendación de herramienta: Recomiendo Validador de memoria. Capaz de monitorear aplicaciones que hacen miles de millones de asignaciones de memoria.

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

Descargo de responsabilidad: diseñé Memory Validator.

La definición de los contadores de perfmon se ha roto desde el principio y, por alguna razón, parece ser demasiado difícil de corregir.

Una buena descripción de la administración de memoria de Windows está disponible en el video ” Misterios de la administración de memoria revelada ” en MSDN: cubre más temas de los necesarios para rastrear memory leaks (por ejemplo, administración de conjuntos de trabajo) pero brinda suficientes detalles sobre los temas relevantes.


Para darle una pista del problema con las descripciones del contador PerfMon, aquí está la historia interna sobre bytes privados de ” Contador de rendimiento de Bytes privados: ¡cuidado! ” En MSDN:

P: ¿Cuándo es un byte privado no un byte privado?

A: cuando no es residente.

El contador Private Bytes informa el cargo de compromiso del proceso. Es decir, la cantidad de espacio que se ha asignado en el archivo de intercambio para contener el contenido de la memoria privada en caso de que se cancele. Nota: Estoy evitando la palabra “reservado” debido a una posible confusión con la memoria virtual en el estado reservado que no está comprometido.


Desde ” Planificación del rendimiento ” en MSDN:

3.3 Bytes privados

3.3.1 Descripción

Memoria privada, se define como memoria asignada para un proceso que no puede ser compartido por otros procesos. Esta memoria es más costosa que la memoria compartida cuando varios procesos de este tipo se ejecutan en una máquina. La memoria privada en dlls no administrados (tradicionales) generalmente constituye una estática de C ++ y es del orden del 5% del conjunto de trabajo total de la dll.

Hay una discusión interesante aquí: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ Mi comprensión de este hilo es que liberar pequeñas asignaciones es no reflejado en bytes privados o conjunto de trabajo.

Larga historia corta:

si llamo

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

entonces los bytes privados reflejan solo la asignación, no la desasignación.

si llamo

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

luego, los bytes privados reflejan correctamente la asignación y la desasignación.