Partage
  • Partager sur Facebook
  • Partager sur Twitter

C# Garbage collector et variables globales

    5 novembre 2011 à 19:16:15

    Salut,

    Je me pose des questions concernant le fonctionnement du garbage collector en ce moment, ayant fait plusieurs analyses concernant l'utilisation de mémoire de mes différentes applications. Selon ce que j'ai pu lire sur le net, il est généralement conseillé de déclarer ses variable "dans la plus petite portée possible" pour chaque méthode, de sorte à optimiser la collection des objets / variables qui ne sont plus référencés et à libérer la mémoire qu'ils utilisaient.

    Je constate de mon côté un comportement différent que je n'arrive pas bien à comprendre, je m'explique. J'ai testé les deux cas de figure pour une application témoin :

    A) Déclaration de toutes les variables dans la plus petite portée possible pour chaque méthode :

    using
    using
    using
    
    namespace App1
    {
       public partial class Form1: Form
       {
       
       public Form1()
            {
                InitializeComponent();
            }
       public methode1()
       {
          int variable1
          int variable2
          //<utilisation des variables 1 et 2 sur diverses opérations>
       }
     }
    }
    


    B) Déclaration des variables en tant que variable globales, accessibles n'importe où dans l'application :

    using
    using
    using
    
    namespace App1
    {
       public partial class Form1: Form
       {
    
        public int variable1
        public int variable2
       
       public Form1()
            {
                InitializeComponent();
            }
       public methode1()
       {
          //<utilisation des variables 1 et 2 sur diverses opérations>
       }
      }
    }
    


    Je constate de façon relativement nette que la quantité de mémoire utilisée est moindre dans le temps et à un instant T en utilisation un système de variable globale dans mon application, plutôt qu'en déclarant chaque variable dans les méthodes dans lesquelles elles sont utilisées. (Et donc potentiellement redéclarées à chaque fois que la méthode est appelée).

    Y'a-t-il quelque chose que je comprends mal à ce sujet ? J'ai besoin de vos lumières. :)
    • Partager sur Facebook
    • Partager sur Twitter
      5 novembre 2011 à 20:34:21

      Le fait que ça prenne moins de mémoire est une illusion.

      En fait le GC va supprimer de la mémoire toutes les variables qui ne peuvent plus être utilisées, donc à la fin de la méthode il supprime ces variables. Si tu les mets en tant que variables membres de la classes (il n'y a pas de globale en C#!) elles restent dans la mémoire et sont réutilisées
      • Partager sur Facebook
      • Partager sur Twitter
      "Il est impossible pour un homme d'apprendre ce qu'il croit déjà connaître"
        6 novembre 2011 à 7:31:40

        Dans ton exemple, ça ne change rien, vu que int est un type valeur, et n'est donc pas géré par le GC.
        • Partager sur Facebook
        • Partager sur Twitter
          6 novembre 2011 à 13:58:09

          Citation : Ice_Keese

          Dans ton exemple, ça ne change rien, vu que int est un type valeur, et n'est donc pas géré par le GC.



          C'est sur ça?

          Parce qu'un élément dans un programme...Qu'il soit de type valeur ou référence, consomme de la mémoire (soit dans la pile, dans le tas)...Lorsqu'il n'est plus utilisé, il serait logique de libérer cette mémoire utilisée.

          Si ce que tu dis est vrai, ça voudrait dire qu'un tel code
          long a = 0;
          while(a < 2000000000)
          {
              long b = a++ - 1;
              Console.WriteLine(b);
          }
          

          va laisser résident dans la pile 2 000 000 000 * 8 = 16 000 000 000 o = 16 Go de valeur numérique qui ne seront jamais libérées o_O ?!
          • Partager sur Facebook
          • Partager sur Twitter
            6 novembre 2011 à 14:21:38

            Citation : Ice_Keese

            Dans ton exemple, ça ne change rien, vu que int est un type valeur, et n'est donc pas géré par le GC.



            Ce n'était que pour illustrer en fait, je fais évidemment cela avec des objets. :)
            • Partager sur Facebook
            • Partager sur Twitter
              6 novembre 2011 à 16:09:58

              Citation : Nisnor

              Citation : Ice_Keese

              Dans ton exemple, ça ne change rien, vu que int est un type valeur, et n'est donc pas géré par le GC.



              C'est sur ça?

              Parce qu'un élément dans un programme...Qu'il soit de type valeur ou référence, consomme de la mémoire (soit dans la pile, dans le tas)...Lorsqu'il n'est plus utilisé, il serait logique de libérer cette mémoire utilisée.

              Si ce que tu dis est vrai, ça voudrait dire qu'un tel code

              long a = 0;
              while(a < 2000000000)
              {
                  long b = a++ - 1;
                  Console.WriteLine(b);
              }
              


              va laisser résident dans la pile 2 000 000 000 * 8 = 16 000 000 000 o = 16 Go de valeur numérique qui ne seront jamais libérées o_O ?!



              Il a raison, les variables de type valeur sont stockés sur la pile, donc forcément l'espace est réutilisé.

              Pou revenir sur le sujet, c'est peut-être pour la simple raison que le GC ne les collecte pas souvent, parce qu'il les mets en génération 1 ou 2.
              • Partager sur Facebook
              • Partager sur Twitter
                6 novembre 2011 à 16:43:59

                @Nisnor : il n'y a évidemment pas de réallocation de la variable b à chaque tour de boucle, puisque comme l'indique Spaz ton entier b est alloué sur la pile et non sur le tas. Et il est d'ailleurs alloué une et une seule fois sur la pile au début de l'exécution de la fonction (et pas du bloc). Le GC ne s'intéresse qu'au tas.

                @Xeaz: tu ne dois pas perdre de vue ce que signifie faire de tes variables des variables membres ("globales") de ta classe. Au sens orienté objet, que ta variable soit locale à une méthode ou membre d'une classe est très différent. A toi de voir si cette variable sert à décrire l'état courant de ton objet ou si c'est une simple variable de travail que tu utilises dans une de ces méthodes. L'aspect "consommation de mémoire" est secondaire.
                • Partager sur Facebook
                • Partager sur Twitter
                  6 novembre 2011 à 17:37:35

                  Citation : Nisnor

                  Citation : Ice_Keese

                  Dans ton exemple, ça ne change rien, vu que int est un type valeur, et n'est donc pas géré par le GC.



                  C'est sur ça?

                  Parce qu'un élément dans un programme...Qu'il soit de type valeur ou référence, consomme de la mémoire (soit dans la pile, dans le tas)...Lorsqu'il n'est plus utilisé, il serait logique de libérer cette mémoire utilisée.


                  Un type valeur est alloué soit sur la pile, soit inline dans un objet. Le GC ne s'occupe que des références, et un type valeur n'est pas accédé par référence. Au yeux du GC, donc, il n'existe tout simplement pas. Dans le cas d'un type valeur membre d'un objet, sa mémoire sera libérée lorsque l'objet lui même sera réclamé par le GC.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 novembre 2011 à 22:55:49

                    Oki...Merci pour vos précisions ^^

                    Le MSDN est bien clair en ce qui concerne les références...Mais concernant les types valeurs, c'est pas dit comment c'est géré...D’où ma question ^^ . (Quoique...J'ai pas épluché la doc sur la gestion de mémoire utilisée par la CLR)
                    • Partager sur Facebook
                    • Partager sur Twitter

                    C# Garbage collector et variables globales

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown