Ramasse-miette (Garbage Collection)
chaps31
Membre
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 ?
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 ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
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
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).
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.
... 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 !
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.
C'est ce que j'avais lu en effet.
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.
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).
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é...
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
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
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"
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.
Dans les sources de Darwin ça s'appelle AutoZone, license open-source Apache.
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 !
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.