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 :

Programme C qui swap mais ne libère pas la mémoire ?


Sujet :

C

  1. #1
    Membre régulier
    Inscrit en
    Décembre 2009
    Messages
    95
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 95
    Points : 77
    Points
    77
    Par défaut Programme C qui swap mais ne libère pas la mémoire ?
    Bonjour a tous,

    Je ne savais pas si je devais poster ma question ici ou dans un coin du forum plus orienté hardware, mais puisque je ne sais pas si le problème vient du programme ou de la gestion de la mémoire en elle-meme ... C'est parti pour ici.

    J'ai donc un programme, écris en C, qui lit des données et construit un index en RAM sur ces données. Théoriquement, plus il y a de donnes inserées, plus l'index est compressé. Le programme en question fait surtout des petites allocations, rarement plus de 600 ou 700KB, beaucoup de réallocations et assez peu de désallocations. Sur des jeux de données de tailles moyens, Valgrind n'indique aucune fuite memoire. Le tout est lancé sur un PC portable tournant sous Ubuntu 14.04 64 bits, 15.4 GB de RAM et 15.7 GB de SWAP.
    Toujours est-il que je me suis lancé il y a peu dans l'indexation (et donc l'insertion) de 4 jeux de données assez important en taille. J'ai laissé tourner le software pendant le weekend, m'attendant a une consommation de la RAM de l'ordre de 13.5 a 14.5 GB de RAM bien que théoriquement, la consommation mémoire pouvait etre beaucoup plus faible. A cela il faut ajouter environ 350 MB de RAM utilisée par le système. Or en revenant du weekend, je trouve le software toujours en train d'insérer le 4eme jeu alors qu'il aurait du finir depuis longtemps et la consommation mémoire est comme indiqué dans les images jointes.

    Nom : screen1.png
Affichages : 273
Taille : 90,3 Ko
    Nom : screen2.png
Affichages : 309
Taille : 61,1 Ko

    Comme vous pouvez le voir, la RAM est presque pleine (15 GB sur 15.4 GB) et le système swap (6.4 GB sur 15.7 GB). J'avoue etre plutot surpris, le programme ne devrait pas utiliser tant de mémoire (15 + 6.4 = 21.4 GB soit plus de 7GB au dela de mes espérances). En revanche, il est indique que le processus ne prend que 10.6 GB de mémoire, ce qui collerai plus avec mes attentes mais pas avec ce qui a été dit précédemment.

    Quelqu'un aurait t-il une idée pour expliquer cette ambiguité dans les chiffres ? Le programme utilise t-il 10.6 GB ou environ 20 GB ? Ou devrait-il utiliser 10.6 GB mais pour une raison quelconque lié a la partition Swap, il ne libère pas la mémoire ?

    Merci d'avance pour vos réponses, toute piste/idée/réponse serait la bienvenue

    Bonne journée !

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Cette histoire de réallocation me rappelle l'histoire de "pourquoi il ne faut pas multiplier par plus du nombre d'or quand on réalloue". Il est possible que ton code fragmente la mémoire.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre régulier
    Inscrit en
    Décembre 2009
    Messages
    95
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 95
    Points : 77
    Points
    77
    Par défaut
    Merci de ta réponse Médinoc.

    Je t'avoue que c'est ce que je me suis dit au départ (j'aurais bien aimé lancer un coup de Massif dessus pour voir comment se comporte le programme avec la mémoire mais ca va prendre des semaines avec les données que j'ai, peut-etre meme des mois ...) mais je ne pense pas que ce soit la cause.

    Tout d'abord, car la mémoire reporté par l'outil système Moniteur (qui au final doit etre une interface graphique pour la commande top) est en terme de mémoire fragmenté il me semble, et pas en terme de mémoire pure alloué par le programme. Du coup, je me retrouve toujours a me demander quelle est la différence entre les 10.6 GB utilisé par le processus d'un coté, et 21.4 GB de RAM et SWAP de l'autre).
    Ensuite, plus de 30% de fragmentation, ca me parait énorme. Je croyais justement que Glib était très performant pour ce genre de petites allocations car il stocke très proche les uns des autres les objets allant dans des classes de petites tailles.
    Pour finir, les jeux insérés sont théoriquement 99.9% identiques entre eux. Le premier jeu inséré prend 13.9 GB de RAM (pas de swap). Le deuxième ne rajoute que 50 MB de RAM. Mon problème est que après l'insertion du deuxième jeu, je ne sais pas ce qu'il s'est passe et je n'ai donc aucune idée de si le programme s'est mis a swapper pendant l'insertion du 3eme jeu ou du 4eme Toujours est-il que le troisième et quatrième jeu ne devrait apporter que peu de mémoire supplémentaire. Mais admettons que l'un de ces deux jeu est plus différents que les autres, ce qui a pousse le système a swapper (mais n'explique pas les "10.6 GB" utilisé par le processus). Je m'interroge maintenant a propos de la fragmentation sur la partition Swap car meme si un jeu est plus différent des autres, je ne m'attend pas a ce qu'il consomme tant de Swap. Est-ce que le système ré-utilise la mémoire swap comme il le ferait avec de la mémoire RAM ? Ou est-ce plus compliqué ? La fragmentation devrait-elle etre la meme sur la partition Swap ? Les realloc sur de la mémoire Swap doivent avoir de très mauvaises perfs non ?

  4. #4
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 148
    Points : 28 113
    Points
    28 113
    Par défaut
    Bonjour,

    Sans avoir les sources de ton programme, difficile de faire une analyse du code.

    Ce qui me chagrine dans tes messages, c'est que je n'ai pas l'impression que tu maîtrises bien les sources ni ce que fait ton programme : tu dis que le second jeu de données devrait être à peu près identique au premier, mais c'est pas sûr, et que la mémoire ne devrait augmenter que de 50Mo, mais là non plus rien n'est certain -- et c'est encore pire pour les jeux 3 et 4...

    De plus, je m'interroge lorsque tu dis :
    Théoriquement, plus il y a de donnes inserées, plus l'index est compressé.
    Est-ce que tu veux dire que plus tu as données, plus l'index est petit, proportionnellement ? ou bien dans l'absolu ?

    Est-ce que tu as essayé de ne faire passer que les jeux de données 1 et 2, en sachant exactement quelles sont les différences entre ces jeux, et en regardant la différence de consommation mémoire ? Et en passant deux fois le même jeu, est-ce que tu n'as bien aucune consommation mémoire supplémentaire ?
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  5. #5
    Membre régulier
    Inscrit en
    Décembre 2009
    Messages
    95
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 95
    Points : 77
    Points
    77
    Par défaut
    Bonjour gangsoleil et merci de ta réponse.

    Pour ce qui est de l'absence des sources, désolé mais je ne peux rien faire a ce niveau la. Le code est lié a mon boulot et doit donc rester confidentiel. De surcroit, le programme est assez complexe, réparti sur plusieurs milliers de lignes, donc localiser le bug (si bug il y a) serait une tache vraiment ardue. Tous ce que je peux certifier, c'est que sur des jeux de données de taille moyens, Valgrind n'indique aucune fuite mémoire.

    A vrai dire, je ne maitrise pas ce que fait le programme dans le sens ou il utilise une structure de données dynamique pour l'indexation. Ainsi, sa représentation interne comme sa taille dépendent fortement des données insérées. Cette structure compresse les données au fur et a mesure qu'elles sont inserées, mais l'index n'est pas proportionnellement plus petit au nombre de donnes inserées. Parfois, les données sont compressibles, parfois non, tout dépend du jeu de données en entrée.

    De meme, les jeux de données sont tellement gros qu'on ne peux pas les comparer entre eux. On pense qu'ils sont 99.9% identique mais exactement, on ne sait pas. Je parle du fait que la mémoire ne devrait augmenter que de 50MB car j'ai realisé un premier test en insérant que le jeu 1 et 2. Le premier jeu inséré prend 13.9 GB de RAM (pas de swap). Le deuxième ne rajoute que 50 MB de RAM. Maintenant, j'ai essayé d'insérer le jeu 1, 2, 3 et 4, avec un comportement prévu pour le jeu 1 et 2, mais pas pour le 3 et/ou 4.

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Bonjour,

    Citation Envoyé par Wizard50 Voir le message
    Bonjour gangsoleil et merci de ta réponse.

    Pour ce qui est de l'absence des sources, désolé mais je ne peux rien faire a ce niveau la. Le code est lié a mon boulot et doit donc rester confidentiel. De surcroit, le programme est assez complexe, réparti sur plusieurs milliers de lignes, donc localiser le bug (si bug il y a) serait une tache vraiment ardue. Tous ce que je peux certifier, c'est que sur des jeux de données de taille moyens, Valgrind n'indique aucune fuite mémoire.
    Cela ne veut pas dire qu'on est sûr qu'il n'y en a pas. Si tu alloues de la mémoire au sein d'une boucle, que tu la libères proprement en dehors de cette boucle, mais que ta boucle ne prend jamais fin (par exemple si c'est la boucle principale d'un système coopératif), alors les allocations mémoires vont continuer à se cumuler indéfiniment.

  7. #7
    Membre régulier
    Inscrit en
    Décembre 2009
    Messages
    95
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 95
    Points : 77
    Points
    77
    Par défaut
    Bonjour Obsidian, merci de ton aide.

    Je comprend le point que tu soulève, cependant mon système n'est pas coopératif d'une quelconque manière: la charge de travail n'est pas distribué sur plusieurs machine et le programme est single-threadé. Jusqu'a maintenant, le programme s'est toujours terminé correctement, avec toute la mémoire désalloué a la sortie, donc il n'y a pas possibilité de boucle infinie. En revanche, il y a possibilité d'une longue boucle ayant énormément d’itérations qui alloue énormément de mémoire (peut-etre est-ce que tu voulais dire dans ton message et dans ce cas je n'avais pas compris cela comme ca) mais je n'ai pas observé ce comportement sur les jeux de données moyens, ni sur l'insertion des jeux énormes 1 et 2.

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Wizard50 Voir le message
    Je comprend le point que tu soulève, cependant mon système n'est pas coopératif d'une quelconque manière: la charge de travail n'est pas distribué sur plusieurs machine et le programme est single-threadé.
    Ça, ça n'empêche pas — en soi — un programme de proposer du multitâche coopératif. Au contraire, c'est même dans ce genre de situation que l'on va retrouver des architectures à boucle principale. Ce va être typiquement le cas des petits serveurs à connexions multiples, comme l'IRC. Mais bon, on va considérer que ce n'est pas ce qui nous occupe présentement.

    Jusqu'a maintenant, le programme s'est toujours terminé correctement, avec toute la mémoire désalloué a la sortie,
    Désalloué par le programme ou par le système d'exploitation parce que ton processus s'est terminé ? Bon, là encore, si valgrind ne se plaint pas, c'est que ce doit être correct de ce côté-là aussi.

    donc il n'y a pas possibilité de boucle infinie.
    Infinie, non, mais à durée indéterminée, ou difficilement déterminable, peut-être. Comme avec la fonction d'Ackermann.

    En revanche, il y a possibilité d'une longue boucle ayant énormément d’itérations qui alloue énormément de mémoire (peut-etre est-ce que tu voulais dire dans ton message et dans ce cas je n'avais pas compris cela comme ca) mais je n'ai pas observé ce comportement sur les jeux de données moyens, ni sur l'insertion des jeux énormes 1 et 2.
    À dire vrai, à ce stade et sans information supplémentaire, ça peut être dû à n'importe quoi. Je ne pense pas que le swap, surtout de cette quantité, soit dû à de la fragmentation. Il faut effectivement monitorer les indices de ta boucle. Soit c'est algorithmique, soit c'est une erreur d'inattention, genre un « i == n » plutôt que « i <= n » qui fait que, dans certains cas, i peut « sauter » la valeur limite et continuer à l'infini, soit c'est carrément un bug structurel, comme un dépassement de tableau, qui irait écraser la valeur de la variable qui le suit immédiatement (comme un indice de boucle…).

Discussions similaires

  1. Réponses: 1
    Dernier message: 22/11/2012, 15h20
  2. un programme windows qui fonctionne mais ne se ferme pas
    Par ketchupi dans le forum Débuter
    Réponses: 1
    Dernier message: 22/04/2011, 20h54
  3. Réponses: 2
    Dernier message: 27/04/2009, 14h09
  4. Une interface qui envoie mais ne reçoit pas
    Par Eusebius dans le forum Développement
    Réponses: 1
    Dernier message: 21/03/2008, 10h27
  5. Réponses: 2
    Dernier message: 07/01/2007, 13h15

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