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!
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
En realidad, el perfil de Visual Studio es muy útil en este tipo de escenarios. –