IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Fuite Mémoire C#


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2014
    Messages : 11
    Par défaut Fuite Mémoire C#
    Bonjour,

    Je reviens vers la communauté en ayant un nouveau soucis, je sature la mémoire de mon PC.

    Même si les objets manipulées peuvent être lourds, il ne justifient pas (je pense) l'utilisation de 2Go de RAM...

    Cela se produit lors de la conversion d'un Catalogue en un SuperCatalogue.

    Voici ce qui est actuellement fait dans la classe Catalogue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public IList<T> result { get; set; }
     
    public Catalogue<ElementCatalogue> ConvertirEnSuperCatalogue()
            {
                SuperCatalogue<ElementSuperCatalogue> catalogue = new SuperCatalogue<ElementSuperCatalogue>();
                catalogue.resultats = new List<ElementSuperCatalogue>();
                foreach (IConvertibleElement element in result)
                {
                    ElementSuperCatalogue elementConverti = element.ConvertirEnSuperElement();
    catalogue.resultats.Add(elementConverti);
                }
    // Autres traitements .....
                return catalogue;
            }
    Le problème se produit lors de la ligne : ElementSuperCatalogue elementConverti = element.ConvertirEnSuperElement();

    J'aimerais savoir quel peut en être la cause.

  2. #2
    Membre Expert
    Avatar de PixelJuice
    Homme Profil pro
    Ingénieur .NET & Game Designer
    Inscrit en
    Janvier 2014
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur .NET & Game Designer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2014
    Messages : 662
    Par défaut
    Bonjour,

    serait-il possible de voir la méthode ConvertirEnSuperElement ?

    A propos , ce n'est pas ça une fuite mémoire , d'ailleurs c'est assez rare d'en avoir en C# (du moins ,beaucoup moins que dans les autres langages) car le code est managé et il y a le Garbage Collector.

    Ton problème, c'est un traitement lourd ou un traitement mal optimisé.

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2014
    Messages : 11
    Par défaut
    La méthode ConvertirSuperElement ressemble à cela (des éléments ont étés supprimés car elle est très longue).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
        public class compoElement : ElementCatalogue, IConvertibleSuperElement
        {
            public long? id { get; set; }
            public MaClasse classe { get; set; }
    	public IList<string> descriptionComplement { get; set; }
            public IList<Substance> substanceList { get; set; }
            public IList<Substance> substance2List { get; set; }
    	// Liste de propriétés suppprimées pour la clarté ...
     
            public ElementSuperCatalogue ConvertirEnSuperElement()
            {
    	    CompositionChimique compo = new CompositionChimique();
     
                compo.idInterne = Convert.ToUInt64(this.id);
     
                compo.id = this.id.ToString();
                compo.nom = this.name;
                compo.dateCrea = this.date;
                compo.dateModif = this.date2;
                compo.mangeable = this.retrocedable;
                compo.buvable = this.perfusable;
                compo.supprime = this.deleted;
    	    // Elements qui sont attribués de la même façon supprimés...
     
     
    	    if (classe != null)
                    compo.classe = Convert.ToUInt64(classe.code);
     
                compo.descComp = new List<string>();
                if (descriptionComplement != null)
                {
                    compo.idATC.Add(this.descriptionComplement);
                }
     
    	    compo.idSubstances = new List<ulong>();
                compo.idSubstance2 = new List<ulong>();
                foreach (Substances subs in subsList)
                {
                    if (subs != null)
                    {
                        switch (subs.number)
                        {
    		    case 1:
                                foreach (Substances sub in subs.subList)
                                {
                                    if (sub != null)
                                    {
                                        string chaineCommande = "SELECT ID FROM CorrespondanceSub1 WHERE IDEXTERNE = :idExterne";
                                        Global.Base.CreerCommande(chaineCommande);
                                        Global.Base.AjouterParametre("idExterne", sub.code, DbType.String, ParameterDirection.Input);
     
                                        try
                                        {
                                            ulong id = Global.Base.RecupererCorrespondance();
                                            compo.idSubstances1.Add(id);
                                        }
                                        catch (Exception e)
                                        {
                                            // Traitement....
                                        }
                                    }
                                }
                                break;
    			    case 1:
                                foreach (Substances sub in subs.subList)
                                {
                                    if (sub != null)
                                    {
                                        string chaineCommande = "SELECT ID FROM CorrespondanceSub2 WHERE IDEXTERNE = :idExterne";
                                        Global.Base.CreerCommande(chaineCommande);
                                        Global.Base.AjouterParametre("idExterne", sub.code, DbType.String, ParameterDirection.Input);
     
                                        try
                                        {
                                            ulong id = Global.Base.RecupererCorrespondance();
                                            compo.idSubstances2.Add(id);
                                        }
                                        catch (Exception e)
                                        {
                                            // Traitement....
                                        }
                                    }
                                }
                                break;
                            default:
                                break;
                        }
                    }
                }
     
    	    //D'autres traitement sont dans cette méthode mais ressemblent au derniers...
                return compo;
            }
        }
    Pourtant la mémoire augmente suite à l'utilisation de cette méthode sans jamais se libérer...

    Serait ce du à l'appel à la base de données ?



    Je viens d'essayer ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    public IList<T> result { get; set; }
     
    public Catalogue<ElementCatalogue> ConvertirEnSuperCatalogue()
            {
                SuperCatalogue<ElementSuperCatalogue> catalogue = new SuperCatalogue<ElementSuperCatalogue>();
                catalogue.resultats = new List<ElementSuperCatalogue>();
                foreach (IConvertibleElement element in result)
                {
    		CompositionChimique  elemente = new CompositionChimique();
                    catalogue.resultats.Add(elementConverti);
                }
    	    // Autres traitements .....
                return catalogue;
            }
    En créant des super éléments (CompoChimique) vide (sans tenir compte des éléments du catalogue normal), je passe déjà de 31 000K en mémoire à 400 000K en fait....
    (Le constructeur vide ne fait rien, il laisse l'initialisation faite par défaut en C#).

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2014
    Messages : 11
    Par défaut
    Je viens de résoudre le problème, il s'agissait d'un DbDataReader qui n'était en fait jamais clos....

    Erreur de débutant...


    Merci à tout ceux qui ont pu réfléchir sur le problème

  5. #5
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Tant mieux si ton problème est résolu, mais je tiens quand même à m'offusquer face à ton code.

    En effet, ton "CreerCommande" ne retourne rien.
    J'imagine donc qu'il implique la création d'un objet persistant sous forme de singleton ou autre...

    Qu'en est-il du multi-threading ? Là ça va pas marcher hein...

    Ensuite, je vois un "AjouterParametre" sans faire référence à l'objet Commande créé plus tôt... Du coup où ajoute un paramètre, mais on sais pas trop où ni comment... ni même à la limite pourquoi : est-on sûr qu'il n'existe pas déjà ?

    Et enfin, et surtout... Ok, on fait la requête... Et on ne ferme jamais rien.
    Visiblement, c'est ce qui a causé ta fuite mémoire.

    C'est évident que tu vas continuer à avoir beaucoup de problèmes de performances avec cette méthode !

    Encapsule si ça te chante la création de SqlCommand et SqlParameter, mais conserve la logique suivante :
    - CreerCommande doit retourner un Objet IDisposable, contenant ton SqlCommand
    - AjouterParameter doit prendre en paramètre ton objet Commande
    - L'utilisation de ton objet Commande doit absolument se faire dans un bloc using !

    Et enfin, car j'ai l'impression que c'est le cas...

    Pas de connexoin SQL persistante à la base de données !
    Tu pourris la mémoire (donc les perfs) :
    - de l'application cliente
    - du serveur

    En effet, tu dois SYSTEMATIQUEMENT établir une nouvelle connexion pour chaque nouvelle Commande (ou lot de Commande à la limite)
    ET DETRUIRE LE PLUS VITE POSSIBLE LA CONNEXION !

    En effet, SQL Server (mais c'est vrai aussi pour Oracle, PostGreSQL, MySQL, DB2 et la plupart des autres SGBD) gère nativement, et implicitement le connection pooling. Par conséquent, conserver une connexion à la base ouverte inutilisé est une hérésie, puisque c'est au pooling de s'en occuper ! Tu empêches le Garbage Collector de .NET de faire son travail, et tu forces ton programme client à conserver des ressources allouées inutilement, et sur le serveur, tu forces à laisser une session et tout son contexte inutilement en mémoire !

    Voilà, j'ai fini de m'offusquer

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2014
    Messages : 11
    Par défaut
    Merci à toi, j'ai effectué sur ce que tu a écrit quelques modifications.

    C'est vrai que je n'ai pas forcement de bonnes notions étant donnée que je n'avais auparavant pas souvent manipulé de base de données dans des programmes...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [tomcat][memoire] java.net.URL et fuite mémoire
    Par Seiya dans le forum Tomcat et TomEE
    Réponses: 6
    Dernier message: 09/03/2009, 10h41
  2. [Fuites mémoire] Je cherche un utilitaire
    Par 10_GOTO_10 dans le forum C++Builder
    Réponses: 8
    Dernier message: 10/02/2005, 10h03
  3. Outil de recherche de fuite mémoire
    Par eag35 dans le forum MFC
    Réponses: 4
    Dernier message: 02/02/2005, 12h46
  4. [SWT]SWT et fuite mémoire(ou pas)
    Par menuge dans le forum SWT/JFace
    Réponses: 2
    Dernier message: 22/06/2004, 21h40
  5. [debug] fuites mémoires
    Par tmonjalo dans le forum C
    Réponses: 3
    Dernier message: 28/07/2003, 17h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo