11
votes

Un compilateur C # conforme peut-il optimiser une variable locale (mais inutilisée) s'il s'agit de la seule référence forte à un objet?

Voir aussi ces ressources connexes: strong> em> p>

  • Est-ce que le garbage collector .NET effectuer une analyse prédictive de code? (sur Stack Overflow) em> li>
  • WP7: Quand GC Considérons une variable locale comme Garbage (article de blog sur MSDN) em> li> ul> Blockquote>

    En d'autres termes: p>

    Peut un objet référencé par un local variables être remis en état avant la la variable est hors de portée (par exemple. parce que la variable est affectée, mais alors pas utilisé à nouveau), ou est-ce objet garanti non admissibles à la collecte des ordures jusqu'à ce que la variable est hors de portée? p> Blockquote>

    Laissez-moi vous expliquer: p>


    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);
    }
    


0 commentaires

3 Réponses :


12
votes

Peu importe ce que le compilateur C # fait - la gigue / gc est autorisé à nettoyer les références locales une fois qu'ils ne sont plus vivants dans un corps de méthode. Regardez les docs pour GC.Kekeealive

Aussi, ce PowerPoint Présentation , surtout de la diapositive 30 à l'envers, aide à expliquer ce que le JIT / GC peut se reproduire.


5 commentaires

Notez également que, dans les constructions de débogage, la variable est explicitement maintenue vivante à la fin de la portée du débogueur à visualiser - ce n'est que dans les constructions de libération que vous verrez ce comportement.


@Andy - Point intéressant. Pas que cela compte, mais je suppose que ce comportement est régi par la gigue?


Et pour la complétude, c'est pourquoi la définition inutilisélocalvar = null à la fin de la méthode est généralement une dés-optimisation.


@damien_the_unbeliever: Merci pour le GC.Kekeekalive Cue, je pense que la documentation MSDN donne une réponse de 95% à ma question. - @henk Holtermann: Cela semble moins sûr que gc.keekeealive ; Un compilateur intelligent n'a-t-il pas pu reconnaître un tel affectation null aussi superflu et l'optimise-la aussi?


Oui, l'optimiseur JIT supprimera les missions nulles. Le collecteur des ordures obtient des signaux pour la durée de vie d'une variable locale du compilateur JIT. GC.Sekeekalive est une version manuelle d'une telle signature, elle ne génère aucun code.



3
votes

Bien que ma question ait été répondue, je pensais poster cette information pertinente que je viens de trouver sur l'article de Blog MSDN " WP7: Quand GC considère-t-il une variable locale comme poubelle " par abhinaba :

[T] Spécification de l'ECMA (ECMA 334 Section 10.9) [...] States

"Par exemple, si une variable locale dans la portée est la seule référence existante à un objet, mais que la variable locale n'est jamais mentionnée dans une éventuelle continuation de l'exécution du point d'exécution en cours dans la procédure, Une implémentation peut (mais elle n'est pas tenue de) traiter l'objet comme non utilisé. "

Cela dit tout. L'article mentionné indique également que la structure .NET (au moins en mode de libération) effectuera une analyse prédictive et des objets libres, tandis que le framework compact ne sera pas (pour des raisons de performance).


0 commentaires

-1
votes

est un compilateur C # conforme autorisé à optimiser les deux premières lignes de cas_2 dans celles de cas_1 si elle voit que non utiliséeLocalvar n'est utilisée que dans un seul endroit, à savoir un argument du constructeur de faim?

Les deux définitions sont équivalentes, de sorte que la transformation de celle de l'autre n'est pas une "optimisation" car non plus efficace.

I.e. Existe-t-il une possibilité que l'affirmation dans le cas_2 pourrait jamais échouer?

Oui. Un compilateur de production n'est pas susceptible de conserver une référence inutilement pour qu'il soit supprimé, le GC ne le verra pas comme une racine globale et collectera cet objet.

Notez que les capteurs de déchets ne voient pas votre programme en termes de variables et de portée. Ces concepts de haut niveau ont été compilés depuis longtemps au moment où votre code accède au collecteur des ordures. Le GC ne voit que des registres, des piles de fil et des variables globales.


2 commentaires

"Les deux définitions sont équivalentes de sorte que la transformation de l'une à l'autre n'est pas une" optimisation "car non plus efficace.", Faire une affectation vs ne faisant pas une mission est la base sur la manière dont la gestion de la mémoire fonctionne, directement liée à la performance. . C'est ce que cela est QU est à propos, le compilateur sera-t-il suffisamment intelligent pour ne pas faire une mission lorsque ce n'est pas nécessaire.


"Faire une affectation vs ne pas faire une mission est la base sur la manière dont la gestion de la mémoire fonctionne". Non ce n'est pas le cas. Vous confondez les caractéristiques du code source avec ce que le GC peut réellement voir. Du point de vue du GC, il n'y a pas de variables locales et il n'y a pas de missions dans les deux cas ici. Par conséquent, ce n'est pas une "optimisation". Les seules contraintes du compilateur C # sont que cela ne peut pas coaler des écrires, mais il n'y a pas de mémoire écrit sur le tas de toute façon ...