Pregunta sobre garbage-collection, .net, c# – ¿Cómo recuperar la memoria no utilizada de la gran cantidad de objetos LOH de varias aplicaciones administradas?

8

Mientras hablaba con un colega acerca de un grupo particular de aplicaciones que utilizaban casi 1,5 G de memoria en el inicio ... me señaló un muy buen enlace enDepuración de producción .NET

La parte que me tiene desconcertada es ...

Por ejemplo, si asigna 1 MB de memoria a un solo bloque, el montón de objetos grandes se expande a 1 MB de tamaño. Cuando libera este objeto, el montón de objetos grandes no libera la memoria virtual, por lo que el montón permanece en un tamaño de 1 MB. Si asigna otro bloque de 500 KB más tarde, el nuevo bloque se asigna dentro del bloque de memoria de 1 MB que pertenece al montón de objetos grandes. Durante la vida útil del proceso, el montón de objetos grandes siempre crece para contener todas las asignaciones de bloques grandes a las que se hace referencia actualmente, pero nunca se contrae cuando se liberan objetos, incluso si se produce una recolección de basura. La Figura 2.4 en la página siguiente muestra un ejemplo de un montón de objetos grandes.

Ahora digamos que tenemos una aplicación ficticia que crea una gran cantidad de objetos grandes (> 85KB), por lo que el montón de objetos grandes crece, por ejemplo, a 200 Megas. Ahora digamos que tenemos 10 instancias de aplicaciones de este tipo ejecutándose ... de modo que se asignaron 2000 megas. Ahora esta memoria nunca se devuelve al sistema operativo hasta que el proceso se apaga ... (es lo que entendí)

¿Hay algún vacío en mi entendimiento? ¿Cómo recuperamos la memoria no utilizada en los diversos LOHeaps? ¿No creamos la tormenta perfecta de OutOfMemoryExceptions?

Actualizar: De la respuesta de Marc, quise aclarar que los objetos LOH no están referenciados, los objetos grandes son uso-n-throw, sin embargo, el montón no se encoge a pesar de que el montón está relativamente vacío después de la oleada inicial.

Actualización # 2: Solo con la inclusión de un fragmento de código (exagerado, pero creo que se entiende). Veo una OutOfMemoryException cuando la memoria virtual alcanza la marca de 1.5G en mi máquina (1.7G en otra). DesdePublicación del blog de Eric L., 'la memoria del proceso se puede visualizar como un archivo masivo en el disco ...', por lo que este resultado es inesperado. Las máquinas en este caso tenían GB de espacio libre en el disco duro. ¿El archivo del sistema operativo PageFile.sys (o la configuración relacionada) impone alguna restricción?

<code>        static float _megaBytes;
        static readonly int BYTES_IN_MB = 1024*1024;

        static void BigBite()
        {
           try
           {
              var list = new List<byte[]>();
              int i = 1;

              for (int x = 0; x < 1500; x++)
              {
                 var memory = new byte[BYTES_IN_MB + i];
                 _megaBytes += memory.Length / BYTES_IN_MB;
                 list.Add(memory);
                 Console.WriteLine("Allocation #{0} : {1}MB now", i++, _megaBytes);
              }
           }
           catch (Exception e)
           {  Console.WriteLine("Boom! {0}", e); // I put a breakpoint here to check the console
              throw;
           }
        }
       static void Main(string[] args)
        {
            BigBite();
            Console.WriteLine("Check VM now!"); Console.ReadLine();
            _megaBytes = 0;

            ThreadPool.QueueUserWorkItem(delegate { BigBite(); });
            ThreadPool.QueueUserWorkItem(delegate { BigBite(); });
            Console.ReadLine();   // will blow before it reaches here
        }
</code>
(respondió al comentario) Marc Gravell

Tu respuesta

3   la respuesta
2

Bueno, si realmente tiene este tipo de patrón de asignación, podría mover sus objetos grandes a otro dominio de aplicación: cuando decida liberar todos los objetos grandes, libere el dominio de aplicación y se lanzará el montón para ese dominio de aplicación.

LOH no es por Appdomain. mfawzymkh
5

Hay una aclaración que me gustaría hacer primero. - Suponiendo que está ejecutando la aplicación como una aplicación de 32 bits, el espacio VA disponible para su proceso es de solo 2 GB, 3 GB si habilitó el interruptor de espacio de dirección grande, por lo que incluso si tiene un archivo de páginas ENORME, no importa si tiene 32 bits. proceso, es importante si ejecuta 64 bits, donde tiene un gran espacio de direcciones.

Objeto con tamaño>85000 bytes se asignan en LOH, tenga en cuenta que es85000 bytes No 85K, también es detalles de la implementación que podrían cambiar. Ahora, volvamos a tu pregunta. El GC anulará la confirmación de los segmentos de LOH que no se usan en 2 situaciones 1- Cuando la presión de la memoria en la máquina es alta (~ 95-98%) 2- Cuando no satisface las nuevas solicitudes de asignación, liberará el valor no utilizado páginas en el LOH

así recuperarás la memoria en uno de estos casos. El hecho de que esté alcanzando un OOM antes de alcanzar el límite de 2 GB podría significar que tiene una fragmentación de VA, la fragmentación de VA ocurre cuando no tiene un espacio de direcciones de VA continuo para satisfacer una nueva asignación, por ejemplo, solicita un segmento de 8 KB y no lo hace. t tiene 2 páginas consecutivas en su VA (asumiendo que el tamaño de la página es 4 K)

puede usar la extensión del depurador! vamap en las herramientas de depuración de Windows para validar esto.

Espero que esto ayude Gracias

3

sin embargo, no olvide queOutOfMemoryException Es por proceso, ya que realmente el disco duro es el factor limitante para la memoria virtual. Eric Lippertblogueó sobre esto recientemente. Por supuesto, eso no evita que se obtenga un bajo rendimiento de toda la paginación ...

Actualizará la pregunta. Los objetos LOH en sí mismos se usan y lanzan en este caso ... una vez que han cumplido su propósito, los objetos LOH se han liberado, pero el montón no se reduce. Considere un componente que realiza cierta serialización de objetos antes de enviarlos por un conducto: en este caso, asigne, por ejemplo, 200 Megas como matrices de bytes, que son basura después de la transmisión de los datos. Gishu
Gracias por el enlace ... adjunto un fragmento de código que me confunde aún más, pero es similar al problema que inició este hilo. Tus pensamientos como siempre son muy apreciados. Gracias por el trabajo que haces en este foro ... Gishu
No estoy seguro de que la edición cambie nada. El punto que intentaba señalar es que tener una bola y una cadena de 200 MB no esnecesariamente un problema. Es probable que la mayoría salga de la memoria principal debido a la inactividad ... Marc Gravell

Preguntas relacionadas