MensajeHola Pablo,

En realidad mi intención fue ilustrar que el 'process recycling' y el 
OutOfMemoryException, aún cuando ambos se relacionan con el consumo de memoria, 
son dos cosas distintas. El propósito de los ejemplos era el de mostrar como se 
podía provocar cada uno de estos eventos sin que fuera necesario que ocurriese 
el otro, pero de ninguna manera pretendía proponer que estos eran los únicos 
mecanismos que los causaban.


..."Caso 1: donde pido toda la memoria junta que si no hay suficiente no se 
recicla."...
FT: Esto es incorrecto. Cuando pedís toda la memoria junta, y no existe 
suficiente memoria para satisfacer la asignación, se produce un 
OutOfMemoryException, pero el proceso *NO* se recicla, aunque si puede quedar 
en un estado inestable si no se toman las medidas necesarias. Esto puede 
ocurrir como en el ejemplo, cuando se solicita una cantidad muy grande de 
memoria, pero también podría suceder con una asignación mucho menor, si no 
existiese suficiente memoria libre. Simplemente elegí en el ejemplo solicitar 
un array de bytes muy grande por un tema de comodidad.


..."Caso 1:
Si yo tengo 78mb libres del sistema operativo, segun el contador Available MB, 
para generar un OutOfMemory deberia estar llenando por lo menos 70Mb de memoria 
en una sola linea de codigo. No desarrolle la aplicacion, pero no creo que sea 
esa la situacion.
Por otro lado, cuando tira un OutOfMemopryException, despues veo requests que 
nunca pueden consumir tanta memoria siguen tirando OutOfMemoryException.
Puede ser que el sistema operativo diga cuando me quedan 78Mb libres, al 
aspnet_wp.exe no le doy un byte mas ?"...
FT: Aunque sea improbable que una única asignación corresponda a 70MB, hay que 
tener en cuenta que si bien la aplicación puede estar solicitando 100 bytes, el 
administrador de memoria del runtime realiza solicitudes al sistema operativo 
en bloques mucho más grandes (creo que 64MB) que luego fracciona para 
satisfacer las necesidades de las aplicaciones. La memoria solicitada no solo 
tiene que estar libre, sino que también debe existir en un bloque continuo, de 
lo contrario se produce un OutOfMemoryException. A medida que se solicita y 
libera memoria en un proceso, esta gradualmente se fragmenta , y es muy posible 
que el bloque de memoria de 78MB que mencionás no se encuentre todo en un mismo 
bloque, por lo tanto cuando el runtime solicita 64MB no existe memoria 
suficiente. Para ilustrar con un caso un tanto forzado, supongamos que la 
memoria total es de 2GB, y que se encuentra totalmente libre excepto por 
bloques de 1MB cada 63MB de memoria asignada. Es decir que salvo 32MB de 
memoria asignada todo el resto se encuentra disponible. Cuando el runtime 
solicita un bloque de 64MB, si bien existe casi 2GB (-32MB) libres, no existe 
un bloque de ese tamaño de memoria continua y por lo tanto la asignación falla. 

Hay que destacar que todo lo que menciono ocurre a nivel del sistema operativo. 
En el heap del runtime ocurren mecanismos similares pera la diferencia es que 
el runtime es capaz de compactar la memoria y eliminar en gran parte la 
fragmentación. Aún así, es también posible que la memoria del runtime se 
fragmente, especialmente cuando se hacen llamados a código no manejado, y 
cuando se fija la memoria mediante 'pinning'.


...Caso 2:
Me surge una duda, segun lo que comentas cuando vas pidiendo memoria en etapas, 
se dispara el GC ... y si no puede liberar se recicla ... pero ese request se 
va a seguir ejecutando en el mismo working process que se origino, por lo tanto 
por mas que se recicle va a necesitar la memoria en ese working process. Es asi 
o hace un traspaso de request de un working process a otro ?...
FT: Esto tampoco es completamente correcto. El GC es un mecanismo inherente a 
la gestión de memoria del runtime, mientras que el reciclado es una 
característica de ASP.NET, y no una consecuencia directa del GC, sino mas bien 
un mecanismo de protección contra fallas en las aplicaciones. El reciclado 
ocurre cuando se supera un límite arbitrario de memoria, bajo la presunción de 
que la aplicación no debería consumir más memoria que la prevista por este 
límite y por lo tanto si esto ocurre es prudente reiniciar la aplicación. El 
limíte establecido en <processModel> para el reciclado no implica que una 
solicitud de memoria no tenga éxito. 

Supongamos que se configuró ASP.NET de tal forma que la aplicación sea 
reciclada cuando supera el 60% de la memoria disponible, que la memoria total 
es de 1GB, y que al comienzo de un request la memoria total asignada es de 
600MB (estoy simplificando 1GB === 1000MB). Si durante la ejecución de 
solicitud se asigna memoria adicional, no es que esta será denegada y el 
proceso se recicla inmediatamente, sino que la solicitud tendrá éxito y 
finalizará normalmente. Sin embargo, el proceso habrá superado el límite 
establecido e iniciará el reciclaje. Todas las solicitudes actualmente en 
ejecución serán procesadas por el proceso que está siendo terminado, mientras 
que cualquier solicitud nueva es atendida por un proceso nuevo que se inicia.  
Mientras las solicitudes en ejecución en el momento en que se produce el 
reciclaje hagan pedidos de memoria 'razonables' - pensá que todavía quedan 40% 
de memoria teóricamente disponible - entonces no hay motivo por el cual no 
deberían finalizar normalmente.

Espero que ahora quede un poco más claro.

Saludos,

Fernando Tubio

----- Original Message ----- 
  From: Pablo A. Allois 
  To: [email protected] 
  Sent: Friday, December 29, 2006 10:52 AM
  Subject: [puntonet] Consulta sobre Process recycling de aspnet_wp.exe


  Bueno, entonces tenemos dos casos ... 
  Caso 1: donde pido toda la memoria junta que si no hay suficiente no se 
recicla.
  Caso 2: donde voy pidiendo la memoria y si lo necesita puede reciclarse.

  Caso 1:
  Si yo tengo 78mb libres del sistema operativo, segun el contador Available 
MB, para generar un OutOfMemory deberia estar llenando por lo menos 70Mb de 
memoria en una sola linea de codigo. No desarrolle la aplicacion, pero no creo 
que sea esa la situacion.
  Por otro lado, cuando tira un OutOfMemopryException, despues veo requests que 
nunca pueden consumir tanta memoria siguen tirando OutOfMemoryException.
  Puede ser que el sistema operativo diga cuando me quedan 78Mb libres, al 
aspnet_wp.exe no le doy un byte mas ?


  Caso 2:
  Me surge una duda, segun lo que comentas cuando vas pidiendo memoria en 
etapas, se dispara el GC ... y si no puede liberar se recicla ... pero ese 
request se va a seguir ejecutando en el mismo working process que se origino, 
por lo tanto por mas que se recicle va a necesitar la memoria en ese working 
process. Es asi o hace un traspaso de request de un working process a otro ?


  Gracias



------------------------------------------------------------------------------
  De: [email protected] [mailto:[EMAIL PROTECTED] En nombre de Fernando Tubio
  Enviado el: Jueves, 28 de Diciembre de 2006 02:50 p.m.
  Para: [email protected]
  Asunto: [puntonet] Consulta sobre Process recycling de aspnet_wp.exe


  Son dos cosas diferentes. El proceso se recicla cuando la memoria utilizada 
por el proceso aspnet_wp.exe supera un límite preestablecido. Un 
OutOfMemoryException ocurre cuando una asignación de memoria falla debido a que 
no existe suficiente memoria disponible para satisfacerla. Cualquiera de estos 
eventos puede ocurrir sin la existencia del otro. Esto se puede ver con un 
ejemplo sencillo. Crea un web form con dos botones, agregando los siguientes 
handlers respectivamente.

  protected void Button1_Click ( object sender, EventArgs e )
  {
      byte [ ] buffer = new byte[ int.MaxValue ];
  }

  private static ArrayList _items = new ArrayList( 1000 );

  protected void Button2_Click ( object sender, EventArgs e )
  {
      for ( int i = 0; i < _items.Capacity; ++i )
      {
          _items.Add( new byte[ 1000000 ] );
      }
  }

  El primer botón asigna una cantidad de memoria que el sistema no puede 
satisfacer y provoca un OutOfMemoryException. Sin embargo, como la memoria 
nunca llega a ser asignada, el proceso continúa su ejecución. En el ejemplo no 
agrego ningún tipo de manejo de errores, pero se podría agregar un catch y 
atrapar el OutOfMemoryException. Por supuesto, dependerá de las circunstancias 
si la aplicación puede recuperarse de este error. Cuando el runtime no puede 
satisfacer una asignación de memoria, automáticamente dispara un GC con la 
esperanza de liberar la memoria necesaria, que es lo que estás observando.

  El segundo botón asigna bloques de memoria que si bien individualmente pueden 
ser satisfechos, eventualmente la memoria consumida eventualmente supera el 
límite establecido en machine.config, y el proceso se recicla. Los valores que 
elegí son suficientes para provocar esto en mi máquina de desarrollo, pero 
pueden variar de acuerdo a la cantidad de memoria RAM y los valores 
configurados en <processModel>.


  Saludos,

  Fernando Tubio
    ----- Original Message ----- 
    From: Pablo A. Allois 
    To: [email protected] 
    Sent: Thursday, December 28, 2006 10:44 AM
    Subject: [puntonet] Consulta sobre Process recycling de aspnet_wp.exe


    Buenos dias señores,

            La consulta viene a raiz de que tengo un servidor en el que corren 
unos webservices en .net 1.0 que cuando llega a cierto punto de uso de memoria 
dispara la exception Systtem.OutOfMemoryException.

            Ya configure el processmodel del machine.config para que el 
aspnet_wp.exe se recicle ... pero cuando llega el momento en que se tiene que 
reciclar sale con un outofmemory y no se recicla.

            La pregunta es ... que puede estar pasando que no permite que se 
recicle el proceso ?

            El servidor es un windows 2000 server sp4 ... IIS 5.
            Corren aplicaciones .net y java.
            Tiene 2Gb de memoria.

     <processModel enable="true" timeout="Infinite"
                idleTimeout="1:00:00" shutdownTimeout="0:00:20" 
                requestLimit="Infinite" requestQueueLimit="5000" 
                restartQueueLimit="10" 
                memoryLimit="20" 
                webGarden="false" cpuMask="0xffffffff"
                userName="*****" password="******"
                logLevel="All" clientConnectedCheck="0:00:05"
                comAuthenticationLevel="Connect" 
comImpersonationLevel="Impersonate"
                responseRestartDeadlockInterval="00:03:00" 
responseDeadlockInterval="00:03:00" 
                maxWorkerThreads="100" maxIoThreads="100"
            />        

            Lo que noto es que al llegar al memorylimit el GC empieza a 
trabajar, y luego de intentar liberar dispara la exception de out of memory.

            Si pueden ser utiles, tengo un log de performance para pasar.


    Saludos!

Responder a