¿Qué es bytes privados, bytes virtuales, conjunto de trabajo?


491

Estoy tratando de usar la utilidad perfmon windows para depurar fugas de memoria en un proceso.

Así es como perfmon explica los términos:

El conjunto de trabajo 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 los conjuntos de trabajo. Si son necesarios, volverán a aparecer 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 de las páginas del disco o de la memoria principal. El espacio virtual es finito y el proceso puede limitar su capacidad de cargar bibliotecas.

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

Estas son las preguntas que tengo:

¿Son los Bytes privados los que debo medir para asegurarme de que el proceso tenga fugas, ya que no involucra bibliotecas compartidas y, si ocurre, alguna fuga vendrá del proceso en sí?

¿Cuál es la memoria total consumida por el proceso? ¿Son los bytes virtuales o la suma de los bytes virtuales y el conjunto de trabajo?

¿Existe alguna relación entre bytes privados, conjunto de trabajo y bytes virtuales?

¿Hay otras herramientas que dan una mejor idea del uso de la memoria?


3
Una herramienta mejor sería valgrind / helgrind, pero desafortunadamente no en Windows :(
Kornel Kisielewicz

¿Es el byte privado que debo medir para asegurarme de que el proceso tenga alguna pérdida? Si los bytes privados de un proceso no crecen, entonces no tiene pérdidas de memoria. Si crecen, podría deberse a pérdidas de memoria y a fragmentación de la memoria. Creo que es difícil decir mirando al crecimiento de bytes privados lo que significa exactamente.

@SergeiKurenkov Una cosa que podemos decir es que NUNCA se debe a la "fragmentación de la memoria".
Jamie Hanrahan

Respuestas:


517

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

Los bytes privados se refieren a la cantidad de memoria que ha solicitado el ejecutable del proceso , no necesariamente a la cantidad que realmente está utilizando . Son "privados" porque (generalmente) excluyen archivos mapeados en memoria (es decir, archivos DLL compartidos). Pero, aquí está el truco, no necesariamente excluyen la memoria asignada por esos archivos . No hay forma de saber si un cambio en los bytes privados se debió al ejecutable en sí, o debido a una biblioteca vinculada. Bytes privados son también no la memoria exclusivamente física; se pueden paginar en el disco o en la lista de páginas en espera (es decir, ya no se usan, pero tampoco se paginan).

Conjunto de trabajo 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 el "Uso de memoria" del Administrador de tareas y ha sido fuente de un sinfín de confusión en los últimos años. La memoria en el conjunto de trabajo es "física" en el sentido de que se puede abordar sin un fallo de página; sin embargo, la lista de páginas en espera también se encuentra físicamente en la memoria, pero no se informa en el Conjunto de trabajo, y es por eso que puede ver que el "Uso de memoria" cae repentinamente cuando minimiza una aplicación.

Los bytes virtuales son el espacio total de direcciones virtuales ocupado por todo el proceso. Esto es como el conjunto de trabajo, en el sentido de que incluye archivos mapeados en memoria (archivos DLL compartidos), pero también incluye datos en la lista de espera y datos que ya han sido paginados y están 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 una carga pesada se sumarán a una cantidad significativamente mayor de memoria que la máquina realmente tiene.

Entonces las relaciones son:

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

Hay otro problema aquí; así como las bibliotecas compartidas pueden asignar memoria dentro del módulo de su aplicación, lo que puede generar falsos positivos potenciales informados 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 los Bytes privados. Improbable, pero posible.

Los bytes privados son una aproximación razonable de la cantidad de memoria que está utilizando su ejecutable y pueden usarse para ayudar a reducir una lista de posibles candidatos para una pérdida de memoria; Si ve que el número crece y crece constantemente y sin cesar, querrá verificar que el proceso no tenga fugas. Sin embargo, esto no puede probar que haya o no una fuga.

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

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


26
Me temo que su respuesta no es del todo correcta. Los bytes privados se refieren a la cantidad de memoria (RAM) que ha solicitado el ejecutable del proceso, no solo la memoria física. Por lo tanto, seguramente puede inspeccionar la mayoría de los casos de pérdida de memoria mediante el monitoreo de bytes privados. Intente :: VisualAlloc para comprometer una gran porción de memoria (digamos 1.5G). Debería poder ver que sus bytes privados son mucho más grandes que el conjunto de trabajo. Lo que demuestra que su "Conjunto de trabajo son los bytes privados más los archivos mapeados en memoria" es incorrecto.
Jay Zhu

44
En realidad, creo que la comprensión de escritura es "Working Set es el Bytes privados en memoria más los archivos mapeados en memoria". Y los bytes privados PUEDEN intercambiarse: puede ver bytes privados más grandes que la memoria física que tiene en la máquina.
Jay Zhu

2
@Aaronaught: Su primera declaración sobre un indicador confiable y apropiado para la depuración es confusa. Los bytes privados son un indicador confiable de una fuga del espacio de memoria de la aplicación. Podría ser una DLL dependiente e indirecta, pero es una fuga en el espacio de memoria de la aplicación. ¿Puede explicar por qué no se puede usar para depurar? un volcado de memoria completo del proceso de la aplicación debería decirnos qué está consumiendo esta memoria. No estoy seguro de entender por qué no se puede usar para depurar. ¿Puedes arrojar algo de luz?
G33kKahuna

@ G33kKahuna: No está claro para mí cómo un volcado de memoria le dirá qué está consumiendo la memoria en algún sentido significativo, a menos que con "qué" quiere decir "qué módulos", pero todo lo que tiene es una instantánea, todavía no puede ver qué módulo realmente pierde la memoria con el tiempo a menos que realice varios volcados con el tiempo y en condiciones estrictamente controladas. Es difícil concebir una estrategia de depuración más ineficiente y poco confiable. Los perfiladores están en todas partes en estos días; usa uno.
Aaronaught

1
Ejecute un objsize completo, esto debería mostrar los objetos anclados en el montón inmediato. Puede confirmar marcando el eeheap -gc. Esto debería mostrar dónde está atascado el volumen. Por lo general, si no hay pistas disponibles con todos los comandos anteriores, sus bytes privados son consumidos por objetos no recopilados en GC. Ahora pase a gchandles o gcleaks. Estos comandos deberían indicarle qué tipos / direcciones de objeto no se pueden asignar. El puntero sigue ahí pero el objeto se ha ido. Este es un problema categórico para los controladores de eventos inéditos.
G33kKahuna

10

No debe intentar utilizar perfmon, el administrador de tareas ni ninguna herramienta como esa para determinar las pérdidas de memoria. Son buenos para identificar tendencias, pero no mucho más. Los números que informan en términos absolutos son demasiado vagos y agregados para ser útiles para una tarea específica, como la detección de pérdidas de memoria.

Una respuesta previa a esta pregunta ha dado una gran explicación de cuáles son los distintos tipos.

Pregunta sobre una recomendación de herramienta: recomiendo Memory Validator. Capaz de monitorear aplicaciones que realizan miles de millones de asignaciones de memoria.

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

Descargo de responsabilidad: diseñé el Validador de memoria.


1
¿Ni siquiera puedo ejecutar un archivo de clase simple (en Java)? ¿Lo que da?
jn1kk

Sospecho que Stephen y Devil están de alguna manera relacionados o incluso clonados ...: D;)
Robert Koritnik

@StephenKellett, ¿hay una versión de prueba?
Pacerier

@Pacerier si sigue el enlace, hay una versión de prueba para las versiones x86 y x64 justo encima de la opción de compra a la izquierda de la página.
Bradley A. Tetreault

10

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 general de la administración de memoria de Windows está disponible en el video " Misterios de la administración de memoria revelados " en MSDN: cubre más temas de los necesarios para rastrear las pérdidas de memoria (por ejemplo, la administración del conjunto de trabajo) pero proporciona detalles suficientes en los temas relevantes.


Para darle una pista del problema con las descripciones del contador de perfmon, aquí está la historia interna sobre bytes privados de " Private Bytes Performance Counter - Beware! " En MSDN:

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

A: cuando no es residente.

El contador de Bytes privados 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 intercambie. Nota: Estoy evitando la palabra "reservado" debido a la posible confusión con la memoria virtual en el estado reservado que no está comprometido.


De " Planificación del rendimiento " en MSDN:

3.3 Bytes privados

3.3.1 Descripción

La memoria privada se define como la memoria asignada para un proceso que otros procesos no pueden compartir. Esta memoria es más costosa que la memoria compartida cuando se ejecutan múltiples procesos en una máquina. La memoria privada en los dlls no administrados (tradicionales) generalmente se compone de estática C ++ y es del orden del 5% del conjunto de trabajo total del dll.


1
¡vota por los ejemplos increíblemente buenos sobre cómo está roto!
Bruno Brant

La primera cita está equivocada. La asignación de "bytes privados" no requiere que nada sea "asignado en el archivo de intercambio" (que realmente se llama el archivo de paginación). Ni siquiera tiene que tener un archivo de paginación para asignar "bytes privados". De hecho, la asignación de bytes privados no usa inmediatamente ningún espacio en ningún lugar , y puede que nunca use tanto como se le asignó.
Jamie Hanrahan el

La segunda cita no es mucho mejor. Los bytes privados utilizados en el código DLL no se asignan necesariamente estáticamente en su mayoría dentro de la DLL. El código DLL es perfectamente gratuito para llamar a VirtualAlloc, HeapAlloc (malloc y nuevo en el CRTL), etc. También intenta describir el tamaño de la memoria privada como un porcentaje del tamaño del conjunto de trabajo, lo cual no tiene sentido. El primero es un tamaño virtual (y será el mismo para cada uso del código con la misma entrada) mientras que el segundo es físico (que puede ser radicalmente diferente de una ejecución a la siguiente, dependiendo de la cantidad de memoria o - hambriento la máquina está).
Jamie Hanrahan el

5

Aquí hay una discusión interesante: 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 se refleja 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);

entonces los Bytes privados reflejan correctamente la asignación y la desasignación.


77
Esto se explica por el hecho de que las funciones de memoria de la biblioteca estándar C usan un montón personalizado o Win32 que es un mecanismo de administración de memoria además de la administración de memoria de nivel de proceso de bajo nivel.
Kyberias

@ Kyberias, ¿cómo podemos llegar debajo de eso?
Pacerier

mientras que (1) libre (malloc (1000)); // ¿Causaría esto que los bytes privados aumenten para siempre?
franckspike

2
@franckspike: no, aumentará hasta cierto punto (generalmente alrededor de 4 kB, pero esto puede variar) y luego se detendrá, porque el CRT reutilizará la memoria previamente liberada en lugar de solicitar nuevas páginas del sistema operativo.
Miral

@Pacerier: puede llamar a VirtualAlloc y VirtualFree.
Jamie Hanrahan el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.