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

Débats sur le développement - Le Best Of Discussion :

Pour ou Contre le Garbage Collector ?


Sujet :

Débats sur le développement - Le Best Of

  1. #461
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Matthieu Brucher Voir le message
    Mais si c'est la question. Et je ne te parle pas de système à 4ko de RAM, je te parle de HPC, genre des petits jouets avec 16Go de mémoire par noeud à se partager à 4 ou 8 processus. J'ai largement de quoi faire n'importe quoi mais je dois tout compter pour faire tenir les calculs dans le moins de processus possibles pour avoir moins de communications et un throughput maximal.
    Et tu as une preuve qu'un langage à GC est une idée stupide ? Ou c'est juste que personne n'a jamais fait ça, alors on ne voit pas pourquoi on le ferait ? Ou un jour quelqu'un a tenté de faire du lisp, ça merdait, et la déduction a été "c'est le GC" ?

  2. #462
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    Et tu as une preuve qu'un langage à GC est une idée stupide ? Ou c'est juste que personne n'a jamais fait ça, alors on ne voit pas pourquoi on le ferait ? Ou un jour quelqu'un a tenté de faire du lisp, ça merdait, et la déduction a été "c'est le GC" ?
    On commence à faire du HPC en Java, mais on a toujours le même problème une fois qu'on utilise de la mémoire, et c'est un problème qu'on a déjà abordé quelques pages auparavant, c'est le déterminisme de la libération mémoire. Mais bon, si tu penses qu'on doit faire du Java en HPC, c'est que tu dois avoir raison

  3. #463
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Matthieu Brucher Voir le message
    On commence à faire du HPC en Java, mais on a toujours le même problème une fois qu'on utilise de la mémoire, et c'est un problème qu'on a déjà abordé quelques pages auparavant, c'est le déterminisme de la libération mémoire. Mais bon, si tu penses qu'on doit faire du Java en HPC, c'est que tu dois avoir raison
    Il faut *vraiment* que les gens arrêtent le "langage à GC" == "Java"...

    Mais donc l'argument "utilisation mémoire serrée" n'est pas le bon, on est d'accord.

    Adjugé !

  4. #464
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    Il faut *vraiment* que les gens arrêtent le "langage à GC" == "Java"...

    Mais donc l'argument "utilisation mémoire serrée" n'est pas le bon, on est d'accord.

    Adjugé !
    Non, je ne fais pas la confusion. Mais je me vois mal faire un traitement HPC en LISP, ou en CaML, ou en autre chose. Java est ce qu'il y a de plus proche des outils actuels (C, C++ ou Fortran). Donc c'est de lui dont je parle pour savoir si on utiliserait des langages à GC pour l'HPC. C#, c'est tout autant limite, même si on a la possibilité d'avoir le déterminisme.

  5. #465
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Citation Envoyé par choupitoupa
    Vu les machines qu'on a à l'heure actuel, on peut se permettre de s'en foutre royalement du gaspillage de ressources...
    Citation Envoyé par epsilon68 Voir le message
    ... moi je ne pense pas que ce soit bien au programme de prevoir de la quantité de memoire inutilement.
    On en revient toujours au même : tout dépend du programme que l'on code à la base.

    Citation Envoyé par Matthieu Brucher
    on libère dès qu'on peut
    Moi ce que je peux reprocher au GC c'est que je ne suis dispensé que de faire les delete, pas les Dispose()

    A la place d'un "ais-je bien libéré ma mémoire et ma ressource ?" je n'ai plus qu'un "ais-je bien libéré ma ressource ?" ce qui est aussi relou à gérer... Donc je trouve pas l'avancée très intéressante.

  6. #466
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par choupitoupa Voir le message
    Vu les machines qu'on a à l'heure actuel, on peut se permettre de s'en foutre royalement du gaspillage de ressources...

    Tant que c'est pas une appli. qui dois absolument être optimisée car elle sert pour un projet ultra sensible, la seule question qu'on à à se soucier à l'heure actuel en tant que développeur c'est : "quel technologie va me permettre d'aller vite et va pas me les briser ?" l'utilisation de la mémoire etc... pour une appli. classique, c'est vraiment secondaire vu la puissance des machines qui tourne dans le commerce actuellement.
    Faut voir ce qu'on appelle une appli classique. Si tu entends par là une appli bas de game, qui sert uniquement à un seul utilisateur pour s'amuser seul dans son coin tu as raison.
    En revanche, pour une véritable appli professionnelle c'est rarement vrai.

    Si tu écris une appli serveur (serveur WEB, service windows...), la question ne se pose même pas : La moindre fuite mémoire deviendra vite une catastrophe.

    Si tu écris une appli client/serveur... ben en fait, c'est la même chose. Les appli utilisateurs lourdes sont souvent déployées dans un environnement TSE ou Citrix. Ca facilite considérablement la maintenance, le déploiement et la gestion de la sécurité. Tous les utilisateurs doivent alors se partager la mémoire du serveur.
    Et 4 Go lorsque ton appli consomme 200 Mo par utilisateur... ça limite vite le nombre d'utilisateur par serveur.
    et ne parlons même pas de la virtualisation la dedans...

    Citation Envoyé par adiGuba Voir le message
    Si la quantité de mémoire utilisé par le GC augmente, c'est que l'application utilise cette mémoire ! Le GC se contente de ne pas libérer cette mémoire immédiatement auprès du système, afin d'éviter de la réallouer un peu plus tard.
    Et en fait, dans la plupart des cas, c'est exactement la même chose sans GC : Une appli alloue rarement sa mémoire directement auprès de l'OS pour la rendre chaque fois qu'on fait un Free. Les performances seraient bien trop catastrophiques.
    On passe par un gestionnaire de mémoire intermédiaire, directement fournit avec le langage utilisé.
    Ce dernier va allouer la mémoire auprès de l'OS par blocs et redécouper ensuite ces blocs en blocs plus petits pour servir les demandes du programme.
    Lorsqu'on fait un Free dans le code, on rend la mémoire au gestionnaire de mémoire. Si on en rend suffisament, il rendra à son tour cette mémoire à l'OS.

    Dans la pratique, la mémoire est libérée et restituée à l'OS non pas au moment où on libère un bloc dans le code, mais au moment où le gestionnaire de mémoire décide de libérer le bloc principal.
    En fait, c'est même pire : Si on a un petit memory leak, ça peut suffir pour que :
    - Le bloc principal soit toujours utilisé pour le gestionnaire mémoire et que ce dernier ne le rende jamais à l'OS. Donc un memory leak peut coûter bien plus cher que la taille de l'allocation qui n'a pas été libérée...
    - Le bloc principal ne contiennent pas un emplacement continu suffisamment grand pour que l'espace inutilisé soit recyclé afin de servir une allocation qui pourrait tenir sans la fuite mémoire.

    On rencontre le même problème, sans fuite mémoire. C'est la fragmentation de la mémoire.

    Je code en Delphi. J'ai instrumenté son gestionnaire mémoire pour pouvoir cartographier la mémoire utilisée par mes applis. Le rapport entre la mémoire allouée par l'appli, et la mémoire réellement utilisée est parfois allucinant.
    J'ai même constaté une appli qui commence un traitement, se gave en mémoire et s'alloue 1 Go dès le début. Puis au fûr et à mesure du traitement, 90 % des allocations sont libérées, ce qui devrait représenter 900 Mo.
    Et bien au fil du traitement, la consomation mémoire auprès de l'OS... reste exactement la même, comme si les libérations n'étaient pas prise en compte.
    A la fin du traitement, les 10% restants sont finalement libérés à leur tour. Et là, la conso mémoire de l'appli tombe d'un coup de 1 Go à 20 Mo...
    J'ai fait le test avec le gestionnaire de mémoire COM. C'est exactement pareil. Sauf que ses performances se dégradent avec le nombre d'allocations (contraitement à celui de Delphi).

    Avec un GC (en tout cas c'est le cas avec celui de .Net), lorsque le GC déclenche, il en profite pour défragmenter la mémoire. On n'a alors plus ce type de problème.

    Moi ce que je peux reprocher au GC c'est que je ne suis dispensé que de faire les delete, pas les Dispose()

    A la place d'un "ais-je bien libéré ma mémoire et ma ressource ?" je n'ai plus qu'un "ais-je bien libéré ma ressource ?" ce qui est aussi relou à gérer... Donc je trouve pas l'avancée très intéressante.
    Personnellement, je considère que tout l'intérêt du GC se trouve dans la résolution des problèmes de fragmentation de la mémoire, et dans l'amélioration des performances de l'application du faite que les allocations mémoires ne coutent quasiment plus rien et qu'elles ne se dégrade pas avec le nombre d'allocation (dans un langage "tout objet" on serait très mal autrement).
    Pour ce qui est de la "libération automatique de la mémoire", ce n'est rien d'autre qu'un piège à débutant (pardon, on appelle ça un argument marketing...)

  7. #467
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Points : 2 467
    Points
    2 467
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    Faut voir ce qu'on appelle une appli classique. Si tu entends par là une appli bas de game, qui sert uniquement à un seul utilisateur pour s'amuser seul dans son coin tu as raison.
    En revanche, pour une véritable appli professionnelle c'est rarement vrai.

    Si tu écris une appli serveur (serveur WEB, service windows...), la question ne se pose même pas : La moindre fuite mémoire deviendra vite une catastrophe.[...]
    La fuite mémoire ce n'est pas exactement la même chose que le gaspillage de ressource. On peut gaspiller sans provoquer aucune fuite. Je ne défend pas vraiment le point de vue de choupitoupa car je ne suis pas d'accord, mais reste qu'une serveur Web qui gaspille des ressources qu'il aurait pû épargner c'est pas forcément la catastrophe. En fait beaucoup d'applications de nos jours gaspillent de la mémoire par exemple. Mais elles ne sont pas pour autant pleine de fuite, c'est-à-dire de ressources qui ne sont jamais libérées.

    Bon certes ça dépend toujours du sens qu'on donne à «*fuite mémoire ».

    Citation Envoyé par Franck SORIANO Voir le message
    Et en fait, dans la plupart des cas, c'est exactement la même chose sans GC : Une appli alloue rarement sa mémoire directement auprès de l'OS pour la rendre chaque fois qu'on fait un Free. Les performances seraient bien trop catastrophiques.
    Comment peux-tu dire ça de manière général ? Bien sûr un bon concepteur/développeur aura fait attention à cela. Mais il se trouve que l'un des deux problèmes les plus répandus au niveau du code, c'est la fuite mémoire. D'où l'intérêt d'un GC quand c'est acceptable pour le produit et disponible. Tu dois oublier que ce n'est pas l'appli, mais le développeur qui pense à allouer l'espace.

    Je ne fais pas l'apologie du GC. Je ne suis ni pour ni contre.

  8. #468
    Expert éminent sénior
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    6 803
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 6 803
    Points : 32 058
    Points
    32 058
    Par défaut
    Pour moi, fuite mémoire, c'est que ce qui est créé à un moment n'est pas détruit au court de l'usage continu du logiciel. Exemple bêbete : je joue à un jeu de guerre, un char est détruit, mais l'instance reste en mémoire(peu importe la cause). Comme on construit un autre char, eh bien la consommation augmente. Pour peu que la bataille s'éternise, la consommation mémoire explose, alors qu'il n'y a toujours que quelques chars qui s'affrontent.

    Ca peut être voulu, au cas ou on veuille afficher les épaves. Mais dans le cas contraire, c'est juste une fuite de mémoire. Rien à voir avec une mauvaise allocation de la mémoire(genre on prépare 1000 instances de chars là ou la bataille moyenne n'en aligne que 20).
    Les 4 règles d'airain du développement informatique sont, d'après Michael C. Kasten :
    1)on ne peut pas établir un chiffrage tant qu'on a pas finalisé la conception
    2)on ne peut pas finaliser la conception tant qu'on a pas complètement compris toutes les exigences
    3)le temps de comprendre toutes les exigences, le projet est terminé
    4)le temps de terminer le projet, les exigences ont changé
    Et le serment de non-allégiance :
    Je promets de n’exclure aucune idée sur la base de sa source mais de donner toute la considération nécessaire aux idées de toutes les écoles ou lignes de pensées afin de trouver celle qui est la mieux adaptée à une situation donnée.

  9. #469
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par NiamorH Voir le message
    Moi ce que je peux reprocher au GC c'est que je ne suis dispensé que de faire les delete, pas les Dispose()

    A la place d'un "ais-je bien libéré ma mémoire et ma ressource ?" je n'ai plus qu'un "ais-je bien libéré ma ressource ?" ce qui est aussi relou à gérer... Donc je trouve pas l'avancée très intéressante.
    La différence c'est que pour les ressources ont doit avoir une libération déterministe : on ne peut pas remettre à "plus tard" leur fermeture, car cela engendrerait des problèmes !


    Citation Envoyé par Garulfo Voir le message
    La fuite mémoire ce n'est pas exactement la même chose que le gaspillage de ressource.
    C'est ce qui s'approche le plus des fuites mémoires "standard" (où on oublie de libérer la mémoire explicitement) : la mémoire est utilisé par des objets qu'on n'utilise plus...



    Matthieu > Il est évident que le coté non-déterministe de la libération de la mémoire via un GC peut s'avérer problématique pour certains types d'application

    a++

  10. #470
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par Garulfo Voir le message
    Comment peux-tu dire ça de manière général ? Bien sûr un bon concepteur/développeur aura fait attention à cela. Mais il se trouve que l'un des deux problèmes les plus répandus au niveau du code, c'est la fuite mémoire. D'où l'intérêt d'un GC quand c'est acceptable pour le produit et disponible. Tu dois oublier que ce n'est pas l'appli, mais le développeur qui pense à allouer l'espace.
    Tout simplement parce que lorsque tu fais un New, tu n'es pas en contact direct avec les fonctions d'allocation mémoire de l'OS.
    Que tu en ais conscience ou non, il y a toujours un gestionnaire mémoire quelque part dans la chaîne du programme (sauf si tu ne travaille qu'avec une pile). Au minimum tu as celui qui t'es fournis par les routines d'allocations mémoire standard de ton langage.

    La gestion de la mémoire est un problème très complèxe : Une appli travaille avec deux types de mémoires. La pile et le (ou les) tas.
    La pile est très simple à gérer. En revanche pour ce qui concerne le tas ça devient vite très tordu : Tu fais une allocation A, puis une allocation B, puis C. Tu libères B : Tu as un trou dans la mémoire entre A et C. Tu fais une allocation D, il faut voir si tu peux réutiliser le trou entre A et C ou s'il est trop petit, placer le bloc après C....
    Les applis modernes effectuent une quantité astronomique d'allocations/libération. C'est encore pire avec les applis objets qui font un très grand nombre d'allocations de très petites taille. Pour gérer tout ça, il faut obligatoirement un gestionnaire mémoire.
    Si chaque application effectuait chacune de ses allocations directement auprès de l'OS, ce dernier serait rapidement saturé à devoir gérer des listes de millions de blocs alloués et passerait un temps considérable à rechercher les emplacements libres pour servir une allocation.
    D'ailleurs, on le voit très clairement lorsqu'on fait appel au gestionnaire de mémoire COM. Au début, tu fais 100 000 allocations en 20 ms. Lorsque tu commence à atteindre les 5 000 000 d'allocations (et pour remplir 4 Go avec des allocations 16 octets tu peux en faire), il faut 45s pour faire ces mêmes allocations.

    Ensuite, tu as encore une autre contrainte : L'OS doit gérer la protection de mémoire pour isoler les processus entre eux et éviter qu'un process ne puisse aller corrompre son voisin.
    Cette protection est réalisée de façon matérielle directement par le micro-processeur. Et le matériel ne va pas s'amuser à gérer 4 Go de mémoire (et je ne parle même pas au delà) avec une granularité à l'octet près.
    Ca veux dire que l'OS est de toute façon contraint d'allouer des blocs mémoires entier de plusieurs Ko pour chaque demande d'allocation d'un processus. Comme dans ton code, tu fais souvent des allocations beaucoup plus petites, il faut bien un gestionnaire mémoire entre les deux...

    Les problèmes que j'ai présenté sont inhérent à la problématique de la gestion de la mémoire. Ils sont résolus par le gestionnaire de mémoire du langage utilisé. Chaque gestionnaire applique sa propre stratégie pour résoudre ces problèmes (et souvent même, ils utilisent plusieurs stratégies), donc selon le gestionnaire ils seront plus ou moins marqués.

    Ensuite bien sûr, tu peux développer ton propre gestionnaire mémoire et demander ta mémoire directement à l'OS. Mais je parle d'une appli telle que la plupart des devs vont la coder.

    Citation Envoyé par el_slapper
    Pour moi, fuite mémoire, c'est que ce qui est créé à un moment n'est pas détruit au court de l'usage continu du logiciel.
    C'est la définition technique d'une fuite mémoire. C'est l'un des trois principal problèmes dans la gestion de la mémoire.
    Cependant, le memory leak, j'ai envie de dire que c'est le plus bénin. Certes il va faire des ravages lorsqu'il va se produire. Mais quelque part, ce n'est qu'un bug comme un autre.
    Le memory leak est très facile à identifier et à corriger.
    On dispose de nombreux outils pour y parvenir. Il suffit de monitorer le gestionnaire mémoire. A la fermeture de l'appli, il sera alors capable de nous sortir la liste des allocations qui lui ont été demandées et qui n'ont pas été libérées. Il ne reste alors plus qu'à capturer la pile d'appel au moment de chaque allocation et on connaitra l'origine de la fuite, à la ligne de code près.
    Un GC arrive à nous protéger contre ce problème.

    Le deuxième problème c'est ce que j'appelle "les libérations tardives". C'est à dire, lorsqu'une application a fini de se servir d'un objet, mais que ce dernier n'est pas détruit pour autant et ne le sera que bien plus tard. C'est très fréquent en Delphi à cause du "owner pattern". Lorsqu'on crée un objet, on lui définit un propriétaire et l'objet sera automatiquement détruit avec le parent. Sauf que si le cycle de vie du parent n'est pas le même que celui de l'enfant, on conserve en mémoire des objets qui n'ont plus lieu d'être. Donc on consomme de la mémoire inutilement.
    En principe ce problème a un impacte plus limité, sauf si la durée de vie du parent est grande. Ca peut même dégénérer en memory leak si le parent (ou la chaîne des parents) reste en vie pendant toute la vie de l'application...
    Cette situation à pour effet qu'à un instant donné, une application arrive à consommer beaucoup plus de mémoire que ce qu'elle en a réellement besoin. Les pics de consommation dû à un besoin ponctuel risques vite de devenir le rythme de croisière de toute l'appli...
    On a le problème avec le cas du parent, mais d'une façon générale, il se présente chaque fois qu'une appli détruit trop tardivement ses objets.
    Ainsi, techniquement parlant ce n'est pas une fuite mémoire puisque l'objet est toujours référencé et sera libéré un jour par l'appli, cependant concrètement, le résultat peut vite devenir le même...

    Ce problème présente de très gros inconvénients :
    - Aucun GC n'est capable de le répérer et de le corriger puisque techniquement ce n'est pas une fuite mémoire.
    - Je ne connais aucun outil capable d'identifier ce problème. Et d'ailleurs, dans la pratique, il est même très difficile se savoir si on se trouve dans ce cas de figure.
    - Beaucoup de développeur n'ont même pas conscience qu'il s'agit bien là d'un défaut de l'appli.

    Enfin, le dernier problème c'est la fragmentation de la mémoire dont j'ai déjà parlé et qui va être d'autant plus aggravée par les deux problèmes précédents.
    Sur ce dernier point, un GC peut défragmenter la mémoire et rammener la gestion du tas à celle d'une pile.
    En revanche, je ne vois aucune solution avec une gestion non managée du code...

    Dans la pratique, tous ces problèmes réunis font rapidement qu'une application peut facilement consommer deux fois plus de mémoire que ce qu'elle en a réellement besoin.
    Juste ce qu'il faut pour diviser par deux la monté en charge d'un serveur et doubler les coûts de production...

  11. #471
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    Le deuxième problème c'est ce que j'appelle "les libérations tardives". C'est à dire, lorsqu'une application a fini de se servir d'un objet, mais que ce dernier n'est pas détruit pour autant et ne le sera que bien plus tard. C'est très fréquent en Delphi à cause du "owner pattern". Lorsqu'on crée un objet, on lui définit un propriétaire et l'objet sera automatiquement détruit avec le parent.
    [...]
    - Aucun GC n'est capable de le répérer et de le corriger puisque techniquement ce n'est pas une fuite mémoire.
    Je dirais que je ne suis pas 100% d'accord
    En effet, un GC ne relève ni de la magie ni de la divination, donc si on garde un lien père-> fils et que le père est vivant, le fils ne sera pas récupéré, même s'il ne sera jamais utilisé.

    En revanche, le GC aide quand même grandement. En effet (si je ne m'abuse), l'usage de ce "owner pattern" est principalement dans un but de... gestion de la mémoire ! Donc si on remplace la gestion par destruction explicite (je détruis le père, ça détruit toute sa descendance) par une gestion complètement automatique (un GC), plus besoin de ce pattern, et donc le risque est amplement réduit.

  12. #472
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    Citation Envoyé par Franck SORIANO
    C'est très fréquent en Delphi à cause du "owner pattern".
    A la base les applications sont conçus statiquement dans Delphi, pour éviter au développeur de faire les allocations mémoires. Au moment de la conception du programme, l'EDI se charge de faire tout le travail d'instanciation des objets à la place du développeur.

    Cependant, pour un fenêtre windows qui va être l'owner de tous les contrôles visuels qu'elle contient, c'est difficilement concevable de détruire la fenêtre sans ses objets. En revanche, il est possible de créer dynamiquement la fenêtre et la libérer en l'a fermant. J'en ai fait l'expérience et ça peut réduire drastiquement la quantité de mémoire nécessaire à l'application.

    Depuis Delphi 2006, le gestionnaire de mémoire est Fastmm de Pierre Le Riche, un projet Open Source. Tes explications sont notamment basées sur le fonctionnement de ce gestionnaire de mémoire.

    J'ai relevé sur un post cette remarque:
    La principale évolution est l'intégration de la bibilothèque FastMM (http://sourceforge.net/projects/fastmm/) dans le projet. Les (ré)allocations mémoires sont optimisées. Le gain est surtout sensible lors de l'importation des grandes bases de données. Le temps de traitement peut être divisé par un facteur 4 dans certains cas.
    Si quelqu'un veut l'améliorer, les sources sont disponibles.

  13. #473
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par alex_pi Voir le message
    Je dirais que je ne suis pas 100% d'accord
    En effet, un GC ne relève ni de la magie ni de la divination, donc si on garde un lien père-> fils et que le père est vivant, le fils ne sera pas récupéré, même s'il ne sera jamais utilisé.

    En revanche, le GC aide quand même grandement. En effet (si je ne m'abuse), l'usage de ce "owner pattern" est principalement dans un but de... gestion de la mémoire ! Donc si on remplace la gestion par destruction explicite (je détruis le père, ça détruit toute sa descendance) par une gestion complètement automatique (un GC), plus besoin de ce pattern, et donc le risque est amplement réduit.
    Le "owner pattern" est un exemple de cas qui conduit à une libération tardive. Mais il y en à encore beaucoup d'autres. Les plus gros problèmes que j'ai pu rencontrés étaient liés à un gestionnaire de cache où le cache avait été conservé alors qu'on n'en avait plus l'utilité. Il est toujours référencé dans le gestionnaire de caches, donc ce n'est pas un leak. Sauf que je perdais quelques centaines de Mo, avec une tendance à l'aggravation...

    Citation Envoyé par chaplin Voir le message
    A la base les applications sont conçus statiquement dans Delphi, pour éviter au développeur de faire les allocations mémoires. Au moment de la conception du programme, l'EDI se charge de faire tout le travail d'instanciation des objets à la place du développeur.
    Ce qui est encore pire, car on alloue alors automatiquement beaucoup de ressources pour traiter des cas de figure qui seront rencontrés dans peut-être 1% des cas...
    C'était la philosophie du RAD dans Delphi. Ca fonctionne pour les petites applis. Mais ce n'est pas utilisable de cette façon à grande échelle.

    Depuis Delphi 2006, le gestionnaire de mémoire est Fastmm de Pierre Le Riche, un projet Open Source. Tes explications sont notamment basées sur le fonctionnement de ce gestionnaire de mémoire.
    Pour ce qui concerne la détection des memory leak, oui complètement.

    Pour le reste, j'ai présenté les problèmes qu'on rencontre dans toute gestion de la mémoire.
    FastMM fait d'ailleurs un très bon travail, en contournant plus ou moins ces problèmes avec une triple stratégie :
    - Pour les allocations de petite taille, il définit des pools d'allocation pré-allouées. De cette façon, les petites allocations peuvent être très rapides et très nombreuses. Chaque pool est dédiié aux allocations d'une certaine taille, ce qui facilite le recyclage des blocs libérés et ainsi limite la fragmentation.
    - Pour les allocations de grande taille, si j'ai bien compris, elles sont effectuées directement auprès de l'OS.
    - Entre les deux, pour les blocs de taille moyenne j'imagine qu'il doit utiliser une gestion plus traditionnelle de la mémoire avec une liste chaînée des blocs libres.

    Le tout, avec un système de promotion qui permet de recycler les blocs mémoires en les faisant passer d'un rôle à un autre.

  14. #474
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Points : 2 467
    Points
    2 467
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    Tout simplement parce que lorsque tu fais un New, tu n'es pas en contact direct avec les fonctions d'allocation mémoire de l'OS.[...]
    J'ai l'impression que tu n'as pas compris ma remarque... ton intervention sous entendait qu'il n'y a pas plus de problème en général sans GC. Or, les statistiques établies prouvent le contraire (cf. les travaux de Boehm) : les fuites mémoires sont une des deux erreurs les plus communes.

    En fait, c'était vrai en 1998... depuis ça a probablement du diminuer vu que les langages à GC sont de plus en plus présent.

    Je ne soutiens pas le GC coute que coute, ce n'est qu'un outil de plus avec ses forces et ses faiblesses. Mais il faut lui reconnaitre son point fort : il évite les fuites mémoires.

    Au passage, je partage la définition de el_slapper sur les fuites mémoires. C'est donc plus qu'un gaspillage temporaire mais un gaspillage permanent. Le GC ne permet pas de s'affranchir du gaspillage temporaire et un humain pourrait faire mieux qu'un GC. Mais le GC ne fait pas — enfin s'il n'est pas lui même buggé — de fuite permanente, alors que les humains en font, même les bons ! C'est ça le problème.

  15. #475
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    Citation Envoyé par Franck SORIANO
    Citation:
    Envoyé par chaplin
    A la base les applications sont conçus statiquement dans Delphi, pour éviter au développeur de faire les allocations mémoires. Au moment de la conception du programme, l'EDI se charge de faire tout le travail d'instanciation des objets à la place du développeur.

    Ce qui est encore pire, car on alloue alors automatiquement beaucoup de ressources pour traiter des cas de figure qui seront rencontrés dans peut-être 1% des cas...
    C'était la philosophie du RAD dans Delphi. Ca fonctionne pour les petites applis. Mais ce n'est pas utilisable de cette façon à grande échelle.
    Pour des architectures Client/Serveur ou N-tiers, c'est une notion élémentaire à connaître avec ou sans GC puisqu'en .NET tu peux utiliser les instructions Using et Dispose pour forcer la libération de l'objet.

  16. #476
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par Garulfo Voir le message
    Mais le GC ne fait pas — enfin s'il n'est pas lui même buggé — de fuite permanente, alors que les humains en font, même les bons ! C'est ça le problème.
    Les GC modernes, oui. Mais les GC d'ancienne génération ne peuvent pas libérer les cycles, par exemple.

  17. #477
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par Garulfo Voir le message
    J'ai l'impression que tu n'as pas compris ma remarque... ton intervention sous entendait qu'il n'y a pas plus de problème en général sans GC. Or, les statistiques établies prouvent le contraire (cf. les travaux de Boehm) : les fuites mémoires sont une des deux erreurs les plus communes.
    En effet. Je voulais surtout souligner le fait qu'on reproche au GC de ne pas libérer immédiatement la mémoire, alors qu'avec une gestion manuelle de la mémoire, ce n'est pas mieux. Et très souvent c'est même pire.

    Citation Envoyé par chaplin
    puisqu'en .NET tu peux utiliser les instructions Using et Dispose pour forcer la libération de l'objet.
    Heu... pour autant que je sache using et dispose ne force pas la libération de l'objet !
    Dispose sert à implementer le dispose-pattern afin de libérer les ressources autre que la mémoire utilisée par un objet.
    Using est un mécanisme bien pratique pour s'assurer que le Dispose sera bien appelé dès qu'on sort de la porté de l'objet.
    En revanche, dans tous les cas, la mémoire ne sera libérée (et le destructeur ne sera appelé) que lors de la prochaine collecte... après tout dépend de ce qu'on entend par "libération de l'objet".

  18. #478
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    En effet. Je voulais surtout souligner le fait qu'on reproche au GC de ne pas libérer immédiatement la mémoire, alors qu'avec une gestion manuelle de la mémoire, ce n'est pas mieux. Et très souvent c'est même pire.
    disons que je pense profondément que cela vient d'une méconnaissance (lacune d'enseignement ?) du fait qu'une instruction free ne libère rien réellement, et de l'explication y afférent..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  19. #479
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    Implementing a Dispose Method

    The pattern for disposing an object, referred to as a dispose pattern, imposes order on the lifetime of an object.

    A type's Disposemethod should release all the resources that it owns. It should also release all resources owned by its base types by calling its parent type's Dispose method. The parent type's Dispose method should release all resources that it owns and in turn call its parent type's Dispose method, propagating this pattern through the hierarchy of base types. To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.

    There is no performance benefit in implementing the Dispose method on types that use only managed resources (such as arrays) because they are automatically reclaimed by the garbage collector. Use the Dispose method primarily on managed objects that use native resources and on COM objects that are exposed to the .NET Framework. Managed objects that use native resources (such as the FileStream class) implement the IDisposable interface.
    Mais, le dispose pattern de .NET est ressemblant au "Owner pattern" de Delphi, même si les buts sont différents.

    Si un gestionnaire de mémoire permet de gagner en performance sur une application, la logique est d'utiliser les recommandations faites dans sa documentation pour arriver aux buts. C'est sûr qu'un moteur mal règlé sera moins efficace, et c'est valable pour n'importe quel outil de développement.

  20. #480
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Points : 2 467
    Points
    2 467
    Par défaut
    Citation Envoyé par Matthieu Brucher Voir le message
    Les GC modernes, oui. Mais les GC d'ancienne génération ne peuvent pas libérer les cycles, par exemple.
    Mais qui s'intéresse à l'ancienne génération ?
    Si on regarde le C++ des anciennes générations ce n'est pas glorieux. Mais aujourd'hui on dispose des smart pointers. Comme je l'ai dit je ne suis pas pour ou contre un GC. S'il est disponible je suis content de l'utiliser à peu près tout le temps. Mais je côtoie aussi beaucoup de scientifique qui utilise des HPC et je sais qu'alors il faut parfois contrôler la gestion de mémoire. Ce qui ne fait que prouver qu'il reste beaucoup de recherche à faire ^_^

Discussions similaires

  1. Garbage collector en C++, pour ou contre ?
    Par Klaim dans le forum C++
    Réponses: 70
    Dernier message: 05/08/2010, 14h03
  2. Le Garbage collector est-il fait pour cela ?
    Par macRiaz dans le forum Android
    Réponses: 16
    Dernier message: 24/02/2010, 00h01
  3. Réponses: 12
    Dernier message: 29/06/2009, 07h20
  4. Réponses: 1
    Dernier message: 03/06/2009, 00h25

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