Ramasse-miette (Garbage Collection)

chaps31chaps31 Membre
08:54 modifié dans API AppKit #1
J'ouvre un débat qu'en pensez-vous ?
Le "Garbage collector" à  l'air très pratique, si on élude le problème qui est que toute application l'utilisant ne pourra tourner que sur 10.5 minimum, la question est : en dehors de projet multimédia où des saccades video sont possibles trouvez-vous que cette manière de gérer les objets et leur place mémoire ralenti réellement les soft qui l'utilise ?

Car si le ralentissement n'est pas perceptible, alors sous Leopard et supérieur on peut définitivement oublier les release, dealloc et autre autorelease non ?

Réponses

  • ChachaChacha Membre
    décembre 2008 modifié #2
    dans 1229523475:

    Car si le ralentissement n'est pas perceptible, alors sous Leopard et supérieur on peut définitivement oublier les release, dealloc et autre autorelease non ?


    Je ne pense pas que le ralentissement soit perceptible. Par contre, c'est vraiment une affaire de goût pour le ramasse-miettes.
    Perso je n'aime pas car :
    -les objets sont détruits dans un ordre non déterministe
    -il faut donc prévoir, si besoin est, une sorte de "pseudo-destructeur", qu'on doit appeler soi-même, pour pallier cet inconvénient qui peut déclencher des erreurs pour la libération des ressources
    -c'est du travail en plus, alors qu'on avait choisi le GC pour s'économiser du code
    -il est plus dur de maà®triser le GC que la gestion mémoire à  la mimine. Si on se penche sur dealloc, finalize, les liens __weak et __strong, NSMakeCollectable() (ce dont on a vite besoin, en fait), alors on se rend compte que le GC... ben c'est super compliqué.

    -les problèmes de la gestion de la mémoire à  la main sont :
      -soit des release en trop, d'où plantage. Mais du coup le diagnostic est "facile" à  faire car on sait où, et qui, plante
      -soit des retain cycles, mais dans ce cas, l'outil "leaks" est assez utile

    Voilà  pour mon opinion, valable aujourd'hui. D'ici quelques mois, aurais-je changé d'avis ?

    +
    Chacha
  • CéroceCéroce Membre, Modérateur
    08:54 modifié #3
    Je ne me suis pas personnellement mis au ramasse-miettes (je dois être le seul en Europe à  encore programmer pour 10.4) mais je vois surtout que ça apporte des complications. Par exemple, on ne peut plus retirer les bindings d'une vue à  sa destruction, puisqu'on ne sait pas quand elle sera détruite.

    Ce que je veux dire, c'est que Cocoa n'est pas trop prévue pour ça, et de fait, certaines choses deviennent difficiles à  faire. Et comme l'écrit Chacha, la gestion mémoire n'est pas ce qu'il y a de plus difficile à  déboguer (notamment grâce à  NSZombie).
  • NoNo Membre
    08:54 modifié #4
    dans 1229531822:

    [...](je dois être le seul en Europe à  encore programmer pour 10.4)[...]


    Ta reflexion est délicieuse... surtout après cette réponse que tu as faite sur un autre post.
  • CéroceCéroce Membre, Modérateur
    08:54 modifié #5
    Ta reflexion est délicieuse... surtout après cette réponse que tu as faite sur un autre post.


    Mais sinon
    Et pour une appli n'utilisant sans doute rien de spécifique 10.3, c'est dommage de ne pas pouvoir la lancer sous 10.2.
    Et pour une appli n'utilisant sans doute rien de spécifique 10.2, c'est dommage de ne pas pouvoir la lancer sous 10.1.
    Et pour une appli n'utilisant sans doute rien de spécifique 10.1, c'est dommage de ne pas pouvoir la lancer sous 10.0.
    Et pour une appli n'utilisant sans doute rien de spécifique Mac OS X, c'est dommage de ne pas pouvoir la lancer sous Système 9.
    ... jusqu'au boulier chinois comme ça, en passant par l'Amiga, l'Oric et la Pascaline.
  • NoNo Membre
    08:54 modifié #6
    dans 1229539395:

    Mais sinon
    Et pour une appli n'utilisant sans doute rien de spécifique 10.3, c'est dommage de ne pas pouvoir la lancer sous 10.2.
    Et pour une appli n'utilisant sans doute rien de spécifique 10.2, c'est dommage de ne pas pouvoir la lancer sous 10.1.
    Et pour une appli n'utilisant sans doute rien de spécifique 10.1, c'est dommage de ne pas pouvoir la lancer sous 10.0.
    Et pour une appli n'utilisant sans doute rien de spécifique Mac OS X, c'est dommage de ne pas pouvoir la lancer sous Système 9.
    ... jusqu'au boulier chinois comme ça, en passant par l'Amiga, l'Oric et la Pascaline.


    ... donc monsieur le développeur-futur-entrepreneur est bien bête d'être "le seul en Europe à  encore programmer pour 10.4", puisque Ceroce nous écrit une fois de plus le contraire !
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2008 modifié #7
    Le truc avec les ramasses-miettes, contrairement aux idées reçues, c'est que comme les désallocation sont gérés en un seul endroit, cela permet plus d'optimisations de ces suppressions, et donc cela permet d'avoir de meilleurs performances qu'une gestion de mémoire classique...
    Bon, il faudrait voir des benchmarks super bien ficelés pour prouver que c'est plus efficace, et bien sûr il en faudrait d'autres pour prouver que ça ralentit l'application... La lenteur du java est plus due à  son système d'exécution qu'à  son ramasse-miette en particulier. ;)
    Donc je reste partagé...

    Pour ce qui est du ramasse-miette d'ObjC 2, je pense qu'il est encore trop jeune pour être jugé, à  mon avis, c'est comme le reste du système, il y a beaucoup de chantiers qui n'ont pas été terminés, j'attends de voir ce que ça donnera, une fois le concept totalement aboutit.

    Ne lui jetons pas la pierre trop tôt, wait & see.
  • schlumschlum Membre
    08:54 modifié #8
    Les garbage collectors peuvent surtout provoquer des leaks avec des cycles de références.
  • psychoh13psychoh13 Mothership Developer Membre
    08:54 modifié #9
    Celui d'Apple est justement conçu pour éviter les fuites mémoires dues aux références cycliques...
  • chaps31chaps31 Membre
    08:54 modifié #10
    dans 1229561738:

    Celui d'Apple est justement conçu pour éviter les fuites mémoires dues aux références cycliques...


    C'est ce que j'avais lu en effet.
  • psychoh13psychoh13 Mothership Developer Membre
    08:54 modifié #11
    Pour qu'un objet ne soit pas collecté il faut qu'il soit référencé par un objet racine... Alors c'est soit un objet sur la pile, soit un objet comme NSApp...
    Si on a un cycle de référence, mais qu'aucun des objets n'est lié à  un objet racine, ils seront tous supprimés.
  • schlumschlum Membre
    décembre 2008 modifié #12
    C'est pas si simple comme problème... Qu'est-ce que tu appelles un objet racine ?
    Un objet d'un cycle peut avoir été référencé par un objet à  garder ; il devient donc objet racine ? Si oui, il n'y a plus que des objets racines dans le cycle...

    Résoudre ces problèmes c'est de la théorie des graphes, et pour que ça soit optimisé ce sont des algorithmes assez complexes (qui restent coûteux pour les grands graphes).
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2008 modifié #13
    Un objet racine c'est soit une variable globale (NSApp et autres static), soit une variable allouée sur la pile, genre quand on écrit NSArray *myArray = [NSArray array]; ce myArray est un objet racine, et les objets avec des références externes.

    Tous les objets collectables sont ces objets racines et tous les objets que l'on peut atteindre à  partir de ces objets racines en suivant les références de type __strong.
    Donc si l'un des objets de ton cycle est référencé par un objet racine, ou qu'il est relié à  un objet racine à  l'aide de références __strong, il n'a pas à  être supprimé, si cette référence disparaà®t, tout le cycle est supprimé...

    dans 1229603910:
    Résoudre ces problèmes c'est de la théorie des graphes, et pour que ça soit optimisé ce sont des algorithmes assez complexes (qui restent coûteux pour les grands graphes).


    Oui, l'algorithme qui va rechercher les objets à  supprimer peut-être long, mais ce qui peut être long aussi c'est la désallocation de la mémoire si elle est faite par petits bouts. Il est beaucoup moins coûteux en ressource de supprimer d'un coup une grosse quantité de mémoire que plusieurs petits morceaux.
  • AliGatorAliGator Membre, Modérateur
    08:54 modifié #14
    dans 1229604742:
    Un objet racine c'est soit une variable globale (NSApp et autres static), soit une variable allouée sur la pile, genre quand on écrit NSArray *myArray = [NSArray array]; ce myArray est un objet racine, et les objets avec des références externes.
    Heu... en Objective-C, tout est dynamique, les objets sont alloués dynamiquement, et à  part les types standards du C (int, float, ...) on ne peut pas allouer d'objet sur la pile. La preuve, on fait bien derrière un "alloc" pour créer un objet (correspondant un peu à  un malloc en C) et on récupère un pointeur. (Bon à  part si on fait des hacks de partout comme on en causait dans le post "Débat Objective-C 2.0" mais bon ça c'est caopilotracté et pas prévu par Apple comme cas). Du coup ta définition de "objet racine" ne me parait tjs pas très limpide :P

    dans 1229604742:
    Oui, l'algorithme qui va rechercher les objets à  supprimer peut-être long, mais ce qui peut être long aussi c'est la désallocation de la mémoire si elle est faite par petits bouts. Il est beaucoup moins coûteux en ressource de supprimer d'un coup une grosse quantité de mémoire que plusieurs petits morceaux.
    C'est toujours une question de compromis... Pas forcément libérer la mémoire tout de suite car ça coûte moins cher de la recycler ou de faire le ménage en une seule fois qu'en plein de petits morceaux, mais pas non plus tout garder à  nettoyer pour le dernier moment car l'emprunte mémoire grossit alors très vite (et les algos de parcours de la mémoire n'en sont en plus alors que plus lents).
    En plus, cette idée de "désallouer plutôt plusieurs objets à  la fois que chaque objet par petit bout à  divers endroits du code" on la retrouve un peu dans les NSAutoreleasePools... où tous les objets auxquels on a envoyé un autorelease ne sont supprimés qu'à  la fin de la RunLoop, tous au même moment... (mais dans un ordre déterminé, eux, contrairement au GC)

    Moi je n'aime pas le GC déjà  sans doute à  cause de l'apriori qu'on lui prête d'être lourd voire lent et d'être plutôt fait pour "ceux qui ont la flemme d'apprendre à  gérer la mémoire correctement", mais même en passant outre cet apriori, j'aime pas non plus :
    - d'une part parce qu'il ne force pas à  réfléchir un minimum à  la conception de ton programme : en continuant dans la voie du "on vous mâche tout pour que vous n'ayez plus rien à  faire même si ça alourdit un peu la machine" ça a qques avantages certes mais au final on voit aussi qu'on ne sait parfois plus rien faire par nous mêmes, et aussi que du coup la programmation semble accessible aux débutants alors que parfois ça masque des problèmes un peu plus complexes qui pour ceux qui ont la pratique paraissent évidents mais pour ceux qui savent pas gérer la mémoire parce qu'ils se disent que le GC fait tout pour eux, arrivent vite à  n'importe quoi...
    - d'autre part parce que c'est vraiment faussement plus simple : on nous présente souvent ça comme "avec le GC plus besoin de se demander si on a fait le bon nombre de retain/release, on crée l'objet et le GC se démerde pour le relâcher qd il n'est plus nécessaire c'est magique vous avez rien à  faire"... alors qu'en fait c'est tout aussi compliqué (voire parfois plus compliqué) d'utiliser le GC que le mécanismes du retain/release (mécanisme en plus que je trouve super simple, il suffit de suivre les 4 règles que donne Apple dans la doc de gestion de mémoire, qui sont enfantines et suivent une logique classique, et pas de pb), car avec le GC on tombe parfois sur des subtilités assez tordues... ou en tout cas si elles sont pas plus tordues qu'avec retain/release, elles sont bien plus difficiles à  corriger quand on tombe sur un bug à  cause de la gestion mémoire (puisqu'on ne gère plus rien).


    Du coup quand on déclare et gère nos variables y'a tout un nouveau concept, vocabulaire, et une autre logique à  adopter, le coup des __weak et __string mais aussi plein d'autres subtilités... qui pour certains semblent peut-être tout aussi compliqué qu'avec retain/release, mais au tout cas ça reste pas aussi simple avec le GC que ça semble l'être de prime abord comme s'est présenté genre "la mémoire ce gère toute seule c'est magique". Donc au final si y'a tout autant de subtilités à  gérer et à  faire gaffe quand on utilise le GC, je préfère rester au retain/release pour lequel tant que je respecte les 4 règles simples indiquées par Apple j'ai jamais de soucis ;)
  • psychoh13psychoh13 Mothership Developer Membre
    08:54 modifié #15
    dans 1229606482:

    dans 1229604742:
    Un objet racine c'est soit une variable globale (NSApp et autres static), soit une variable allouée sur la pile, genre quand on écrit NSArray *myArray = [NSArray array]; ce myArray est un objet racine, et les objets avec des références externes.
    Heu... en Objective-C, tout est dynamique, les objets sont alloués dynamiquement, et à  part les types standards du C (int, float, ...) on ne peut pas allouer d'objet sur la pile. La preuve, on fait bien derrière un "alloc" pour créer un objet (correspondant un peu à  un malloc en C) et on récupère un pointeur. (Bon à  part si on fait des hacks de partout comme on en causait dans le post "Débat Objective-C 2.0" mais bon ça c'est caopilotracté et pas prévu par Apple comme cas). Du coup ta définition de "objet racine" ne me parait tjs pas très limpide :P


    Bon, je vais préciser ma pensée, j'ai dit "variable allouée sur la pile", pas "objet allouée sur la pile". :P
    Une variable de la pile est toujours une référence de type __strong (et pas __string comme à  la fin de ton message :P), donc l'OBJET alloué dynamiquement dont tu mets la référence dans la VARIABLE allouée sur la pile est considéré comme un objet racine, et donc tous les objets qui y sont reliés en __strong ne seront pas collectables.


    PS: je précise que tout est dit dans la doc, je ne sors rien comme par magie de mon chapeau. ;D
  • schlumschlum Membre
    08:54 modifié #16
    dans 1229604742:

    Oui, l'algorithme qui va rechercher les objets à  supprimer peut-être long, mais ce qui peut être long aussi c'est la désallocation de la mémoire si elle est faite par petits bouts. Il est beaucoup moins coûteux en ressource de supprimer d'un coup une grosse quantité de mémoire que plusieurs petits morceaux.


    Encore faut-il que cette mémoire soit contiguë (donc nécessite en plus un tri...)
    Et encore, même pour de la mémoire contiguë, je ne vois pas trop comment optimiser les "free"
  • psychoh13psychoh13 Mothership Developer Membre
    08:54 modifié #17
    Les fonctions malloc et free sont réécrites pour être optimisées quand on conçoit un garbage collector.
  • schlumschlum Membre
    08:54 modifié #18
    dans 1229608799:

    Les fonctions malloc et free sont réécrites pour être optimisées quand on conçoit un garbage collector.


    Ben oui, mais réécrites comment ? tu fais des réallocations pour les objets susceptibles d'être libérés en même temps ?
    On ne peut avoir que des approches empiriques qui s'avèrent désastreuses pour certains cas.
  • psychoh13psychoh13 Mothership Developer Membre
    08:54 modifié #19
    Boah si tu veux tu peux aller voir le code source du GC d'Objective-C 2.0... :P

    Dans les sources de Darwin ça s'appelle AutoZone, license open-source Apache. :D
  • schlumschlum Membre
    08:54 modifié #20
    Notes d'Apple concernant l'impact du GC sur les performances :
    http://developer.apple.com/releasenotes/Cocoa/GCReleaseNotes/
    http://developer.apple.com/ReleaseNotes/GraphicsImaging/RN-CoreImage/

    Notez qu'ils parlent même d'instabilité dans certains cas !
  • psychoh13psychoh13 Mothership Developer Membre
    08:54 modifié #21
    Ouaip, c'est pour ça qu'en tant que jeune technologie je suis assez réticent à  l'utiliser.
    Cependant, le concept est bien, mais il faut, de toutes façons, toujours faire attention au code qu'on écrit, et utiliser un GC ne dispense pas de coder proprement et de pas utiliser trop d'allocation. :D
Connectez-vous ou Inscrivez-vous pour répondre.