Cosas rápidas que se deben comprobar cuando se experimentan niveles elevados de memoria en ASP.NET

En este artículo se describen las cosas rápidas que se deben comprobar cuando se experimenta una gran cantidad de memoria en Microsoft ASP.NET.

              Versión original del producto: ASP.NET
Número de KB original: 893660

Este artículo comenzará con algunos problemas comunes, acciones para solucionar estos problemas y una breve explicación de por qué estas situaciones pueden causar problemas.

columna Voz de soporte técnico de ASP.NET

En la columna Voz de soporte técnico de abril de 2005, proporcionamos involuntariamente un vínculo al archivo incorrecto. En lugar de vincular a una descarga para el servicio web, vinculamos al archivo XML devuelto por el servicio web. Ese vínculo se ha corregido. Si desea revisar el artículo con el archivo correcto adjunto, consulte Actualizaciones de páginas dinámicas mediante XMLHTTP.

Lo que se considera memoria alta

Obviamente, esta pregunta depende del volumen y la actividad de aplicaciones específicas. En general, la memoria alta es cuando la memoria del proceso de trabajo de ASP.NET (Aspnet_wp.exe) o del proceso de trabajo de Internet Information Services (IIS) (W3wp.exe) aumenta constantemente y no vuelve a un nivel cómodo.

En términos generales, un nivel cómodo sería inferior a 600 MB en el espacio de direcciones de memoria de usuario predeterminado de 2 GB. Una vez que el nivel de memoria sea mayor que ese nivel cómodo, vamos a hacer menos de lo que deberíamos estar. Este comportamiento puede afectar a otras aplicaciones que se ejecutan en el sistema.

La clave es comprender que algunas aplicaciones requieren más memoria que otras. Si supera estos límites, puede agregar más memoria o agregar otro servidor a la granja de servidores web (o considerar una granja de servidores web). La generación de perfiles también se recomienda en estos casos. Puede permitir a los desarrolladores crear aplicaciones más eficientes. En este artículo, veremos una situación en la que se observa un aumento de la memoria de forma coherente hasta que el servidor deja de funcionar.

Configuración de la aplicación para la depuración

Una razón para una memoria alta que vemos aquí en Compatibilidad es cuando tiene la depuración, el seguimiento o ambos habilitados para la aplicación. La habilitación de la depuración y el seguimiento es una necesidad al desarrollar la aplicación. De forma predeterminada, al crear la aplicación en Visual Studio .NET, verá el siguiente atributo establecido en el archivo Web.config :

<compilation
 ...
 debug="true"
 />

o

 <trace
 enabled="true"
 ...
 />

Además, cuando realice una compilación final de la aplicación, asegúrese de hacerlo en modo de versión, no en modo de depuración. Una vez que esté en producción, la depuración ya no debe ser necesaria. Realmente puede ralentizar su rendimiento y comer su memoria. Establecer este atributo significa que cambia algunas cosas sobre cómo controlar la aplicación.

En primer lugar, la compilación por lotes se deshabilitará, incluso si se establece en este compilation elemento. Significa que crea un ensamblado para cada página de la aplicación para que pueda entrar en él. Estos ensamblados se pueden dispersar aleatoriamente en el espacio de memoria, lo que dificulta la búsqueda del espacio contiguo para asignar memoria.

En segundo lugar, el executionTimeout atributo (<elemento httpRuntime>) se establece en un número alto, reemplazando el valor predeterminado de 90 segundos. Está bien al depurar, ya que no puede tener el tiempo de espera de la aplicación mientras recorre pacientemente el código para encontrar los errores. Sin embargo, es un riesgo significativo en producción. Significa que si tiene una solicitud no autorizada por cualquier motivo, se mantendrá en un subproceso y continuará cualquier comportamiento perjudicial durante días en lugar de unos minutos.

Por último, creará más archivos en la carpeta Archivos de ASP.NET temporales . Y (el System.Diagnostics.DebuggableAttribute espacio de nombres System.Diagnostics se agrega a todo el código generado, lo que puede provocar una degradación del rendimiento.

Si no obtiene nada más de este artículo, espero que obtenga esta información. Dejar la depuración habilitada es incorrecta. Vemos este comportamiento con demasiada frecuencia y es tan fácil de cambiar. Recuerde que se puede establecer en el nivel de página. Asegúrese de que todas las páginas no la establezcan.

Concatenación de cadenas

Hay aplicaciones que compilan la salida HTML mediante código del lado servidor y simplemente creando una cadena HTML grande para enviar al explorador. Está bien, pero si va a compilar la cadena mediante + y & concatenación, es posible que no tenga en cuenta cuántas cadenas grandes está compilando. Por ejemplo:

string mystring = "<html>";
mystring = mystring + "<table><tr><td>";
mystring = mystring + "First Cell";
mystring = mystring + "</td></tr></table>";
mystring = mystring + "</html>";

Este código parece bastante inofensivo, pero esto es lo que se almacena en la memoria:

<html>
<html><table><tr><td>
<html><table><tr><td>First Cell
<html><table><tr><td>First Cell</td></tr></table>
<html><table><tr><td>First Cell</td></tr></table></html>

Es posible que piense que solo está almacenando la última línea, pero está almacenando todas estas líneas. Puede ver cómo se puede salir de la mano, especialmente cuando se crea una tabla grande, quizás mediante un bucle a través de un conjunto de registros grande. Si es lo que está haciendo, use nuestra System.Text.StringBuilder clase para que solo almacene la cadena grande. Consulte Uso de Visual C# para mejorar el rendimiento de la concatenación de cadenas.

.NET Framework Service Pack 1 (SP1)

Si aún no ejecuta .NET Framework SP1, instale este SP si tiene problemas de memoria. No voy a entrar en grandes detalles, pero básicamente, con SP1 ahora estamos asignando memoria de una manera mucho más eficiente. Básicamente, estamos asignando 16 MB a la vez para objetos grandes en lugar de 64 MB a la vez. Todos nos hemos movido y todos sabemos que podemos empaquetar mucho más en un coche o camión si usamos muchas cajas pequeñas en lugar de unas cajas grandes. Es la idea aquí.

No tengas miedo de reciclar periódicamente

Reciclamos grupos de aplicaciones en IIS cada 29 horas de forma predeterminada. El proceso de Aspnet_wp.exe continuará hasta que finalice la tarea, reinicie IIS o reinicie el equipo. Este comportamiento significa que este proceso podría estar ejecutándose durante meses. Es una buena idea que algunas aplicaciones simplemente reinicien el proceso de trabajo cada par de días o así, en un momento conveniente.

Preguntas que se van a formular

El anterior eran todas las cosas que se pueden corregir rápidamente. Sin embargo, si tiene problemas de memoria, hágase estas preguntas:

  • ¿Estoy usando muchos objetos grandes? Más de 85 000 KB se almacenan en un montón de objetos de gran tamaño.

  • ¿Estoy almacenando objetos en estado de sesión? Estos objetos permanecerán en la memoria durante mucho más tiempo que si los usa y los elimina.

  • ¿Estoy usando el Cache objeto ? Cuando se usa sabiamente, es una gran ventaja para el rendimiento. Pero cuando se usa de forma imprudible, terminas con mucha memoria usada que nunca se libera.

  • ¿Estoy devolviendo recordsets demasiado grande para una aplicación web? Nadie quiere ver 1000 registros en una página web. Debe diseñar la aplicación para que nunca obtenga más de 50 a 100 registros en un solo viaje.

Depuración

No me meteré en la configuración de WinDbg. Pero puede usar los siguientes comandos para ver qué es exactamente en la memoria, si desea solucionar problemas más complicados.

!eeheap -gc

Este comando le mostrará la cantidad de memoria administrada que tiene. Si este valor es alto, hay algo que el código administrado está compilando.

!dumpheap -stat

Este comando tardará bastante tiempo en ejecutarse, incluso horas si la memoria es grande. Pero este comando le proporcionará una lista de todos los objetos, cuántos de cada tipo y cuánta memoria usa cada uno. (Por ejemplo, para la StringBuilder clase , verá muchos System.String objetos)

Una vez que haya encontrado un objeto que toma mucha memoria, escarba más mediante el siguiente comando:

!do <addr>

Puede obtener la dirección del objeto que está buscando en el dumpheap comando .

Intentaremos incorporar más formas de usar esta herramienta de diagnóstico para situaciones específicas en estas columnas. ¡Háganos saber si estamos haciendo un buen trabajo!

Artículos de memoria y rendimiento

Conceptos básicos y sugerencias de rendimiento del recolector de elementos no utilizados

Desarrollo de aplicaciones High-Performance ASP.NET

ASP.NET supervisión del rendimiento y cuándo alertar a los administradores

Mejora del rendimiento y la escalabilidad de las aplicaciones .NET