11

Véase también estos recursos relacionados:¿Puede un compilador de C# conforme optimizar una variable local (pero no utilizada) si es la única referencia fuerte a un objeto?


En otras palabras:

Puede un objeto referenciado por una variable local ser reclamadas antes de la variable sale del ámbito (por ejemplo. porque la variable está asignada, pero no se volvió a utilizar), o ¿ese objeto está garantizado para ser inelegible para la recolección de basura hasta que la variable salga del alcance?

Me explico:


void Case_1() 
{ 
    var weakRef = new WeakReference(new object()); 

    GC.Collect(); // <-- doesn't have to be an explicit call; just assume that 
        //  garbage collection would occur at this point. 

    if (weakRef.IsAlive) ... 
} 

En este ejemplo de código, que, obviamente, tengo que planificar la posibilidad de que el new'ed object sea reclamado por el recolector de basura; por lo tanto, la declaración if.

(Tenga en cuenta que estoy usando weakRef con el único propósito de comprobar si el new'ed object es todavía alrededor.)


void Case_2() 
{ 
    var unusedLocalVar = new object(); 
    var weakRef = new WeakReference(unusedLocalVar); 

    GC.Collect(); // <-- doesn't have to be an explicit call; just assume that 
        //  garbage collection would occur at this point. 

    Debug.Assert(weakRef.IsAlive); 
} 

El principal cambio en este ejemplo de código de la anterior es que el new'ed object está fuertemente referenciado por una variable local (unusedLocalVar). Sin embargo, esta variable nunca se usa nuevamente después de que se haya creado la referencia débil (weakRef).


Pregunta: es un conformando compilador de C# permite optimizar las dos primeras líneas de Case_2 en los de Case_1 si se ve que unusedLocalVar sólo se utiliza en un solo lugar, es decir, como un argumento a la WeakReference constructor? es decir, ¿hay alguna posibilidad de que la afirmación en Case_2 pueda fallar alguna vez?

Respuesta

11

No importa lo que haga el compilador de C#: el JITter/GC puede limpiar referencias locales una vez que ya no estén vivos en un cuerpo de método. Mire los documentos para GC.KeepAlive

Además, este powerpoint presentation, especialmente desde la diapositiva 30 en adelante, ayuda a explicar qué puede hacer el JIT/GC.

+4

También tenga en cuenta que, en las versiones de depuración, la variable se mantiene explícitamente viva hasta el final del alcance para que el depurador pueda verla; solo en las compilaciones de lanzamiento verá este comportamiento. –

+0

@Andy - punto interesante. No es que importe, pero supongo que este comportamiento está gobernado por JITter. –

+4

Y, para completar, es por eso que configurar 'unusedLocalVar = null' en el _end_ del método suele ser una desoptimización. –

3

Si bien mi pregunta ha sido contestada, yo pensé que había puesto esta pieza relevante de la información que acabo de encontrar en el blog artículo de MSDN "WP7: When does GC Consider a Local Variable as Garbage" por abhinaba:

[L] a la especificación ECMA (ECMA 334 Sección 10.9) [& hellip;] estados

“Por ejemplo, si una variable local que está en el ámbito es la única referencia existente a un objeto, pero esa variable local nunca se hace referencia en cualquier posible continuación de la ejecución de el punto de ejecución actual en el procedimiento, una la implementación puede (pero no es obligatorio) tratar el objeto como que ya no se usa. "

Esto lo dice todo. El artículo mencionado también dice que el .NET Framework (al menos en modo Release) realizará análisis predictivos y liberará dichos objetos, mientras que .NET Compact Framework no lo hará (por razones de rendimiento).

0

Es un compilador de C# conforme permitido optimizar las dos primeras líneas de Case_2 en los de Case_1 si ve que unusedLocalVar sólo se utiliza en un solo lugar, es decir, como un argumento para el constructor WeakReference?

Las dos definiciones son equivalentes, por lo que la transformación de una a la otra no es una "optimización", porque ninguna es más eficiente.

es decir, ¿hay alguna posibilidad de que alguna vez falle la afirmación en Case_2?

Sí. No es probable que un compilador de producción retenga una referencia innecesariamente, por lo que se eliminará, el GC no lo verá como una raíz global y recogerá ese objeto.

Tenga en cuenta que los recolectores de basura no ven su programa en términos de variables y alcance. Esos conceptos de alto nivel ya han sido recopilados cuando el código llega al recolector de basura. El GC solo ve registros, grupos de hilos y variables globales.

Cuestiones relacionadas