2011-04-13 19 views
8

Tengo una aplicación C# /. NET 4.0 que cuando la inicio muestra dos ventanas con aproximadamente una docena de controles. Cuando ejecuto mi programa (depurar o liberar no importa), incluso antes de hacer algo en él, veo en el Administrador de tareas/Monitor de recursos que mi programa ya tiene más de 450 MB de memoria privada. Me doy cuenta de que Task Manager no es la forma más confiable de medir el uso de memoria, pero es uno de los más visibles para mis usuarios.¿Por qué mi programa Winforms reserva tanta memoria virtual?

Cuando ejecuto el análisis de rendimiento de asignación de memoria VS2010 .NET, para una ejecución completa de mi programa, informa de aproximadamente 5 MB de RAM asignados para objetos administrados (mi programa normalmente también usa algunos objetos no administrados, pero son muy pequeño y para simplificar esta investigación los he deshabilitado, aunque sin ningún efecto notable). Del mismo modo, si llamo EmptyWorkingSet() desde psapi.dll después de que se haya mostrado mi formulario principal, mi memoria privada se reduce a ~ 3.5 MB.

Ya he consultado las preguntas sobre las huellas de memoria here y here, pero esas preguntas parecen estar relacionadas con programas que aparecen como un par de docenas de megabytes. Mi programa muestra casi 500MB, lo que parece mucho más preocupante.

No me puedo imaginar todo eso desde arriba; ¿Por qué existe una gran discrepancia entre el generador de perfiles de VS y el Administrador de tareas?

Actualización: Curiosamente, si hago un comentario sobre la parte de InitializeComponent() que configura las ImageLists, el número en el Administrador de tareas permanece por debajo de 10MB. Tengo dos juegos de PictureBoxes e ImageLists en los que PictureBox muestra una de cuatro imágenes, según el botón de opción de un grupo de botones de opción.

Estas líneas de código son los que parecen desencadenar el aumento de memoria masiva:

// 
// directionImageList 
// 
this.directionImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("directionImageList.ImageStream"))); 
this.directionImageList.TransparentColor = System.Drawing.Color.White; 
this.directionImageList.Images.SetKeyName(0, "Dir1.png"); 
this.directionImageList.Images.SetKeyName(1, "Dir2.png"); 
this.directionImageList.Images.SetKeyName(2, "Dir3.png"); 
this.directionImageList.Images.SetKeyName(3, "Dir4.png"); 
// 
// modeImageList 
// 
this.modeImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("modeImageList.ImageStream"))); 
this.modeImageList.TransparentColor = System.Drawing.Color.White; 
this.modeImageList.Images.SetKeyName(0, "Mode1.png"); 
this.modeImageList.Images.SetKeyName(1, "Mode2.png"); 
this.modeImageList.Images.SetKeyName(2, "Mode3.png"); 

estoy usando ImageLists para que pueda utilizar la transparencia. Las imágenes de modo son 100x100 y ocupan < 26KB de espacio de disco cada una. Las imágenes de Dirección son 208x277 de forma predeterminada y aproximadamente 75 KB en el disco. Sé que png es un formato comprimido, pero incluso sin comprimir en la memoria, no esperaría cientos de megabytes para estas siete imágenes.

¿Hay alguna ineficiencia de la que tenga conocimiento, y hay una forma alternativa de mostrar dinámicamente imágenes con transparencia?

Conclusión: Algo es sospechoso con la clase ImageList. A veces perderá el canal alfa, y está causando que mi programa reserve más memoria de la que necesita. También se estaba ralentizando el tiempo para dibujar el formulario principal inicialmente (tanto durante la ejecución como en el diseñador).

Volcar las dos ImageLists redujo mi programa a 10 MB de RAM mucho más saludables. ¡Gracias por todas las sugerencias a todos!

+0

El administrador de tareas no es la forma más sofisticada de medir la memoria, pero debajo de las cubiertas utiliza contadores PerfMon, por lo que debe ser tan preciso como cualquier otro mecanismo. Tenga en cuenta que la columna "Uso de la memoria" en el administrador de tareas es el uso de la memoria privada; puede agregar una columna para "Tamaño de memoria virtual" en "Seleccionar columnas" (o simplemente use 'perfmon.exe') – Justin

+0

En realidad, el perfil de Visual Studio es muy útil en este tipo de escenarios. –

Respuesta

0

de PNG tienen la transparencia ya. Simplemente haga que el blanco sea un color transparente y guarde la imagen. Entonces úselos normalmente.

+0

Originalmente tenía una lista de imágenes porque no podía conseguir que algunas de las partes blancas de las imágenes aparecieran como transparentes. Finalmente encontré una herramienta para hacer eso y simplemente cargué mis imágenes de los recursos, volcando las ImageLists. El programa ahora tiene 10MB mucho más saludables, e incluso el diseñador es mucho más ágil. Entre el canal alfa que ocasionalmente se corrompe y la alta asignación de memoria, parece que algo está pasando con la clase ImageList. Gracias por toda la ayuda. – Troyen

1

.Net framework se diseñó para ejecutarse lo más rápido posible dados los recursos disponibles. La aplicación continuará consumiendo más y más memoria tal como se solicitó (y está fácilmente disponible), solo se soltará cuando llame específicamente al recolector de basura o cuando otra aplicación necesite los recursos que está acaparando.

Minimice la aplicación y debería ver una mejor representación de cuánta memoria está usando la aplicación.

si vuelve a usarlo, permanecerá en el estado de recursos inferiores hasta que se use y se consuma nuevamente.minimizarlo de nuevo para ver cuánto se usa (no) de nuevo. esto está integrado en el sistema de gestión de memoria .net frameworks.

+0

El solo hecho de iniciar el programa me tiene a ~ 459MB. Minimizarlo reduce un megabyte más o menos. Quiero decir, podría entender si se ha estado ejecutando durante mucho tiempo y estaba asignando un montón de cosas, pero estoy confundido de por qué tanto se reserva desde el principio. Especialmente cuando VS Profiler dice que realmente no estoy asignando casi tanto. Es una discrepancia de más de 450 MB, por lo que algo está apagado. – Troyen

+0

El cartel decía ** 450MB ** no 45MB - aunque lo que dices es cierto, el hecho de que se esté consumiendo una cantidad tan grande de memoria definitivamente es indicativo de algún tipo de problema. – Justin

+0

¿Está usando gráficos para su UI? o pintando con fondos transparentes en sus controles de usuario ... ¿está asignando una gran cantidad de objetos en la GUI? –

0

En primer lugar, ¿has probado Debug Diag? Analizará un volcado de su proceso y le dará algunos gráficos ingeniosos de memoria que podrían ayudarle a descubrir quién ha asignado toda esa memoria.

Además, asegúrese de que ni su .exe compilado ni ninguno de sus ensamblados referidos/cargados sea muy grande, es muy posible que todos los ~ 500MB sean dlls cargados. Esto podría suceder si (por ejemplo) se han incorporado recursos grandes en el ensamblaje.

+0

Estoy tratando de verificar Debug Diag ahora. Como mencioné en los comentarios anteriores, mi exe tiene un tamaño de 568 KB. Importación algunas funciones de cuatro DLL no administradas que no están incrustadas en mi programa con un tamaño total combinado de ~ 1MB. Hago referencia a las cosas de Excel Interop, pero eso es todo. – Troyen

+0

@Troyen También [VMMap] (http://technet.microsoft.com/en-us/sysinternals/dd535533) (mencionado en la publicación que vincula a Priyank) también parece ser muy útil para este tipo de cosas. – Justin

2

Mi propia experiencia con este problema es que tenía imágenes de 24 bits en mi imageList mientras tenía la opción de 32 bits establecida en la configuración de la lista de imágenes.

He configurado 24 bits en las propiedades de la lista de imágenes y el problema desapareció. Eso parece ser un error que alguien debería publicar en MS =)

Lo siento por mi inglés.

Cuestiones relacionadas