sensores recolector recoleccion japon inteligentes inteligente hacer fundacion contenedores como clasificacion chile bote basura c# .net generics types garbage-collection

c# - recolector - ¿Se recolecta basura de tipos genéricos/tipos genéricos?



recolector de basura inteligente (1)

Para responder a tu primera pregunta:

Las construcciones genéricas de tipos no se recopilan.

Sin embargo, si construye C<string> y C<object> , el CLR realmente genera el código para los métodos solo una vez; ya que se garantiza que la referencia a la cadena y la referencia al objeto sea del mismo tamaño, puede hacerlo de forma segura. Es bastante inteligente. Sin embargo, si construye C<int> y C<double> , el código de los métodos se genera dos veces, una para cada construcción. (Suponiendo que el código para los métodos se genera en absoluto, por supuesto, los métodos se jit a pedido, es por eso que se llama jitting).

Para demostrar que no se recopilan los tipos genéricos, cree un tipo genérico

class C<T> { public static readonly T Big = new T[10000]; }

C<object> y C<string> comparten cualquier código generado para los métodos, pero cada uno obtiene sus propios campos estáticos, y esos campos vivirán para siempre. Cuantos más tipos construyas, más memoria se llenará con esas grandes matrices.

Y ahora sabes por qué esos tipos no se pueden recolectar; no tenemos forma de saber si alguien intentará acceder a un miembro de uno de esos conjuntos en cualquier momento en el futuro. Como no sabemos cuándo va a ser el último acceso a la matriz, tienen que vivir para siempre y, por lo tanto, el tipo que la contiene debe vivir para siempre.

Para responder a su segunda pregunta: ¿Hay alguna forma de realizar montajes emitidos dinámicamente que se recopilen?

Sí. La documentación está aquí:

http://msdn.microsoft.com/en-us/library/dd554932.aspx

Es bien sabido en .NET que los tipos no son basura, lo que significa que si juegas con f.ex. Reflection.Emit, tienes que tener cuidado de descargar AppDomains y demás ... Al menos así es como solía entender cómo funcionan las cosas.

Eso me hizo preguntarme si los tipos genéricos son basura recolectada, para ser más precisos: genéricos creados con MakeGenericType , digamos ... por ejemplo basados ​​en la entrada del usuario. :-)

Así que construí el siguiente caso de prueba:

public interface IRecursiveClass { int Calculate(); } public class RecursiveClass1<T> : IRecursiveClass where T : IRecursiveClass,new() { public int Calculate() { return new T().Calculate() + 1; } } public class RecursiveClass2<T> : IRecursiveClass where T : IRecursiveClass,new() { public int Calculate() { return new T().Calculate() + 2; } } public class TailClass : IRecursiveClass { public int Calculate() { return 0; } } class RecursiveGenericsTest { public static int CalculateFromUserInput(string str) { Type tail = typeof(TailClass); foreach (char c in str) { if (c == 0) { tail = typeof(RecursiveClass1<>).MakeGenericType(tail); } else { tail = typeof(RecursiveClass2<>).MakeGenericType(tail); } } IRecursiveClass cl = (IRecursiveClass)Activator.CreateInstance(tail); return cl.Calculate(); } static long MemoryUsage { get { GC.Collect(GC.MaxGeneration); GC.WaitForFullGCComplete(); return GC.GetTotalMemory(true); } } static void Main(string[] args) { long start = MemoryUsage; int total = 0; for (int i = 0; i < 1000000; ++i) { StringBuilder sb = new StringBuilder(); int j = i; for (int k = 0; k < 20; ++k) // fix the recursion depth { if ((j & 1) == 1) { sb.Append(''1''); } else { sb.Append(''0''); } j >>= 1; } total += CalculateFromUserInput(sb.ToString()); if ((i % 10000) == 0) { Console.WriteLine("Current memory usage @ {0}: {1}", i, MemoryUsage - start); } } Console.WriteLine("Done and the total is {0}", total); Console.WriteLine("Current memory usage: {0}", MemoryUsage - start); Console.ReadLine(); } }

Como puede ver, los tipos genéricos se definen como ''posiblemente recursivo'', con una clase ''cola'' que marca el final de la recursión. Y para garantizar que GC.TotalMemoryUsage no esté haciendo trampa, también abrí el Administrador de tareas.

Hasta aquí todo bien. Lo siguiente que hice fue disparar a esta bestia y mientras esperaba un "Sin memoria" ... noté que, a diferencia de mis expectativas, no consumía más memoria con el tiempo. De hecho, muestra una ligera caída en el consumo de memoria a tiempo.

¿Puede alguien por favor explicar esto? ¿Los tipos genéricos son realmente recopilados por el GC? Y si es así ... ¿hay también Reflection.Emit casos que son basura recolectada?