yugioh traduccion net invocar example espaƱol collector .net garbage-collection clr

.net - traduccion - garbage collector yugioh



Para GC.Collect o no? (4)

Leyendo este documento antiguo pero clásico Escribiendo aplicaciones administradas de alto rendimiento - Un manual , me encontré con la siguiente declaración

El GC es autoajustable y se ajustará según los requisitos de memoria de las aplicaciones. En la mayoría de los casos, la invocación programática de un GC dificultará esa sintonización. "Ayudar" al GC al llamar a GC.Collect probablemente no mejorará el rendimiento de sus aplicaciones

Estoy trabajando con aplicaciones que, en un momento dado, consumen mucha memoria. Cuando termine con el código que consume esa memoria, llamo a GC.Collect. Si no lo hago me sale de la excepción de memoria. Este comportamiento es inconsistente, pero en términos generales, el 30% del tiempo me sale de la memoria. Después de agregar GC.Collect nunca obtuve esta excepción de memoria. ¿Mi acción está justificada a pesar de que este documento de mejores prácticas lo desaconseja?


En general, GC.Collect no debería ser necesario. Si sus imágenes existen en una memoria no administrada , asegúrese de usar GC.AddMemoryPressure y GC.RemoveMemoryPressure apropiada.


La mayoría de la gente diría que hacer que su código funcione correctamente es más importante que hacerlo rápido. Por lo tanto, no funciona el 30% del tiempo cuando no llama a GC.Collect() , lo que supera todas las demás inquietudes.

Por supuesto, eso lleva a la pregunta más profunda de "¿por qué recibes errores de OOM? ¿Hay algún problema más profundo que deba solucionarse, en lugar de solo llamar a GC.Collect() ?

Pero el consejo que encontraste habla de rendimiento. ¿Te importa el rendimiento si hace que tu aplicación falle el 30% del tiempo?


Parte de lo que sucede en el GC es que los objetos en la memoria son generacionales , de modo que las generaciones anteriores se recolectan con más frecuencia que otras. Esto ayuda a ahorrar rendimiento al no intentar recopilar objetos de larga duración todo el tiempo.

Con eso en mente, pueden suceder dos cosas cuando se llama GC.Collect() . La primera es que acabas pasando más tiempo haciendo colecciones. Esto se debe a que las colecciones de fondo normales seguirán ocurriendo además de su manual GC.Collect (). La segunda es que permanecerá en la memoria por más tiempo , ya que forzó algunas cosas en una generación de orden superior que no necesitaba ir allí. En otras palabras, usar GC.Collect () por sí mismo es casi siempre una mala idea.

Hay algunos casos en los que el recolector de basura no siempre funciona bien. Uno de ellos es el montón de objetos grandes. Esta es una generación especial para objetos más grandes que un tamaño determinado (80,000 bytes, IIRC, pero eso podría ser antiguo ahora). Esta generación casi nunca se recoge y casi nunca se compacta . Eso significa que, con el tiempo, puede terminar con muchos agujeros importantes en la memoria que no se liberarán. La memoria física no se usa realmente y está disponible para otros procesos , pero aún así consume espacio de direcciones dentro de su proceso, de los cuales está limitado a 2 GB de forma predeterminada.

Esta es una fuente muy común para las excepciones de OutOfMemory: en realidad no está usando tanta memoria, pero tiene todo este espacio de direcciones ocupado por agujeros en el montón de objetos grandes. Con mucho, la forma más común en que esto sucede es agregar repetidamente a cadenas o documentos grandes. Probablemente este no sea usted, porque en este escenario no hay una cantidad de llamadas a GC.Collect () companct la LOH, pero en su caso parece ayudar. Sin embargo, esta es la fuente de la gran mayoría de las excepciones de OutOfMemory que he visto.

Otro lugar donde el recolector de basura no siempre funciona bien es cuando ciertas cosas hacen que los objetos permanezcan enraizados. Un ejemplo es que los controladores de eventos pueden evitar que se recoja un objeto. Una forma de evitar esto es asegurarse de que cada operación += para suscribir un evento tenga una operación -= correspondiente para cancelar la suscripción. Pero, de nuevo, es poco probable que un GC.Collect () ayude aquí: el objeto todavía está enraizado en alguna parte y, por lo tanto, no se puede recolectar.

Esperamos que esto le brinde una vía de investigación para resolver su problema subyacente que ocasiona la necesidad de utilizar GC.Collect () en primer lugar. Pero si no es así, por supuesto, es mejor tener un programa que funcione y no un programa que falla. En cualquier lugar que use GC.Collect (), me aseguraré de que el código esté bien documentado por la razón por la que lo necesita (sin excepciones) y los pasos y datos exactos necesarios para reproducirlo de manera confiable para que los futuros programadores que lo deseen para eliminar esto puede estar seguro de cuándo es seguro hacerlo.


Según su descripción, suena como si no se desecharan los objetos Dispose , o si no está configurando valores de miembro que serán reemplazados a nulos antes de la operación. Como ejemplo de este último:

  • Obtener tabla, mostrar en cuadrícula
  • (Actualización de hits del usuario)
  • El formulario está deshabilitado mientras se actualizan los datos
  • La consulta vuelve, los nuevos datos se completan en la cuadrícula

Puede limpiar la cuadrícula mientras tanto, ya que está a punto de ser reemplazada de todos modos; temporalmente tendrá ambas tablas en la memoria (innecesariamente) mientras se reemplaza si no lo hace.