3

Supposons que j'ai une méthode C# comme ceci: (évidemment pas de code réel)Quand la méthode local .NET est-elle éligible aux objets GC?

byte[] foo() 
{ 
    var a = MethodThatReturns500mbObject(); 
    var b = MethodThatReturns200mbObject(a); 
    byte[] c = MethodThatReturns150mbByteArray(b); 
    byte[] d = UnwiselyCopyThatHugeArray(c); 
    return d; 
} 

Comme vous pouvez le deviner par la dénomination, les objets qui sont retournés par ces méthodes sont gigantesques. Des centaines de mégaoctets de RAM totale requis par chacun, bien que les deux premiers objets soient composés de millions d'objets plus petits au lieu d'un gros morceau comme les deux derniers tableaux.

Nous allons bientôt l'optimiser en une solution de streaming, mais en attendant, je voudrais m'assurer qu'au moins, nous n'empêchons pas le GC des objets précédents lors de l'exécution du code pour produire les objets suivants.

Ma question est la suivante: l'objet a sera-t-il admissible au GC dès que MethodThatReturns200mbObject (a) sera de retour? Sinon, quelle est la meilleure façon de faire savoir au GC qu'un 500Mo attend de l'être?

Le cœur de ma question est de savoir si la détermination de "cet objet n'a pas de références" .NET GC est assez intelligent pour savoir que a ne peut pas être référencé après MethodThatReturns200mbObject(a) renvoie. Même si var a est encore théoriquement disponible pour le code ultérieur, a n'est référencé nulle part en dessous de la deuxième ligne de la méthode. En théorie, le compilateur pourrait faire savoir au GC que a n'est pas référencé. Mais en pratique, je ne suis pas sûr de savoir comment il se comporte. Savez-vous?

+0

'GC.KeepAlive()' aurait pas une grande utilité si toutes les variables ont déjà été maintenues vivant jusqu'à la fin de leur portée. –

+0

En mode release, oui, le compilateur est assez intelligent pour marquer 'a' en tant que candidat pour le garbage collection au moment où il n'est plus utilisé. [Cette réponse] (https://stackoverflow.com/questions/17130382/understanding-garbage-collection-in-net/17131389#17131389) peut aussi être utile – Rob

Répondre

1

This post explains it with examples.

En théorie, le compilateur pourrait laisser le GC savoir qu'un est non référencé. Mais en pratique, je ne suis pas sûr de savoir comment il se comporte. Savez-vous?

La bonne réponse est que cela dépend de la configuration du projet si l'objet sera admissible à la collecte des ordures à la fin de la méthode. Comme discuté dans Quand dois-je utiliser GC.KeepAlive? (qui décrit également le but de GC.KeepAlive - en bref, c'est un moyen de référence ou "en utilisant" une variable en s'assurant que l'optimiseur ne va pas optimiser l'utilisation), le garbage collector pourrait décider de collecter objets dès qu'ils ne sont plus utilisables par aucun code d'exécution . Cela peut très bien se produire dans des situations où il serait valide d'accéder à une référence (au moment de la compilation), mais aucun code n'a été écrit.

Cependant, lors de la compilation et de l'exécution de code en mode débogage, le compilateur empêche cela de faciliter le débogage. En conséquence, la méthode mise en œuvre correcte de notre test comprend un préprocesseur directive:

Une autre bonne lecture When do I need to use GC.KeepAlive?

+1

La réponse liée est une bonne lecture, et était exactement ce que Je cherchais. Merci! –