1. John Siracusa
    1. Mountain Lion
      1. Introduction
      2. Achat et installation
      3. Changements d'interface (1)
      4. Changements d'interface (2)
      5. Changements d'interface (3)
      6. Applications (1)
      7. Applications (2)
      8. Applications (3)
      9. Applications (4)
      10. Applications (5)
      11. iCloud(1)
      12. iCloud(2)
      13. iCloud(3)
      14. Gatekeeper(1)
      15. Gatekeeper(2)
      16. Retina et HiDPI
      17. Fourre-tout (1)
      18. Fourre-tout (2)
      19. Fourre-tout (3)
      20. Fourre-tout (4)
      21. Fourre-tout (5)
      22. Fourre-tout (6)
      23. Recommandations
      24. Deux pères, un fils
    2. Lion
      1. Introduction
      2. Installation
      3. Revoir les fondamentaux
      4. Redimensionnement des fenêtres
      5. Et voici pour les cinglés
      6. La gestion des fenêtres
      7. Le modèle de document
      8. le modèle des processus
      9. Les éléments internes (1)
      10. Les éléments internes (2)
      11. ARC
      12. Le système de fichiers
      13. Ses modifications dans Lion
      14. Documents, résolution
      15. Le Finder
      16. Mail, Safari
      17. Fourre tout (1)
      18. Fourre tout (2)
      19. Recommendations
    3. Snow Leopard
      1. Introduction
      2. Le ticket d'entrée
      3. L'installation
      4. Nouvel aspect
      5. Détails internes
      6. Quick Time X
      7. Système de fichiers
      8. Faire plus avec plus
      9. LLVM et Clang
      10. Les blocs
      11. Concurrence
      12. Grand Central Dispatch
      13. Asynchronicité
      14. Open CL
      15. La différence...
      16. Quick Time Player
      17. Le Dock
      18. Le Finder
      19. Exchange
      20. Performances
      21. Fourre tout (1)
      22. Fourre tout (2)
      23. Le futur
    4. Leopard
      1. Introduction
      2. L'héritage
      3. Nouvel aspect 1
      4. Nouvel aspect 2
      5. Le noyau
      6. 64 bits
      7. FS Events
      8. Core animation
      9. Quartz GL
      10. Core UI
      11. Détails internes
      12. Le Finder
      13. Le Dock
      14. Time Machine
      15. Performances
      16. Pot pourri
      17. Demain
    5. Tiger
      1. Introduction
      2. Retour sur le passé
      3. Nouvel aspect de Tiger
      4. Mises à jour du noyau
      5. Le lancement
      6. Les méta-données
      7. Attributs étendus
      8. Listes de contrôle d'accès
      9. Spotlight 1
      10. Spotlight 2 : analyse et potentiel
      11. Types de fichiers
      12. Méta-données : la fin
      13. Quartz
      14. Quartz 2D Extreme
      15. Core Image
      16. La vidéo sous Tiger
      17. Dashboard
      18. Le Finder
      19. Les performances
      20. Pot pourri
      21. Conclusion
    6. Panther
      1. Introduction
      2. Les précédents
      3. L'installation
      4. Nouvel aspect
      5. Performances
      6. Changement rapide d'utilisateur
      7. Gestion des fenêtres
      8. Exposé
      9. Le Finder
      10. Performance du Finder
      11. Toujours le même
      12. Safari
      13. XCode
      14. Conclusion
    7. Jaguar
      1. Introduction
      2. Le nom
      3. L'installation
      4. Modifications d'Unix
      5. Dévelopeurs...
      6. Quoi de neuf
      7. Rendezvous
      8. Quartz Extrême
      9. Performance
      10. Compositions
      11. Le Finder
      12. Applications
      13. Sherlock
      14. Le portrait
    8. Puma
      1. Prelude
      2. Introduction
      3. Installation
      4. Réglages système
      5. Performance
      6. Redimensionnement des fenêtres
      7. Utilisation de la mémoire
      8. Diagnostics de mémoire
      9. L'environnement Classique
      10. L'interface Utilisateur
      11. Le Finder
      12. Extensions de fichiers
      13. Divers, conclusion
    9. Cheeta (Mac OS X 10.0)
      1. Qu'est ce que Mac OS X
      2. Installation
      3. Le démarrage
      4. Utilisation de la RAM
      5. Performance
      6. Performance des applications
      7. Stabilité
      8. L'interface utilisateur
      9. Le Finder
      10. Le navigateur du Finder
      11. Le Finder (divers)
      12. L'interface utilisateur
      13. Os X Classique
      14. Système de fichiers
      15. Unix
      16. Applications
      17. Conclusion
    10. Les débuts de MacOsX
      1. 1999 : OSX DP2
      2. 2000 : Quartz et Aqua/a>
      3. Fin de la lune de miel
      4. la première bêta publique
      5. 2001 : Mac OS X 10.0
      6. Un investissement
    11. Finder Spatial
      1. Introduction
      2. Interfaces spatiales
      3. Le Finder spatial
      4. Le concierge
      5. Un nouveau Finder
      6. Le browser
      7. Le browser spatial
      8. Finder et méta-données
      9. Les modèles
      10. Pensées finales

Lion (10)




Le compte de référence automatique

Depuis 2005, je me suis beaucoup intéressé publiquement à l'évolution à long terme du langage de programmation d'Apple et des framework d'applications, à Objective C, et Cocoa, en allant jusqu'à imaginer une crise technologique possible dans le futur.

Quand le futur est arrivé, j'ai reconsidéré le problème du langage d'Apple et du futur des APIs à la lumière de la pénétration spectaculaire d'Apple dans le marché des mobiles et de la croissance sans précédent qu'elle avait permise. Vous pouvez vous-même lire mes conclusions, mais l'essentiel est que je suis toujours inquiet à ce sujet, et je pense que Apple devrait l'être aussi. Le succès cache les difficultés et Apple a été si profitable ces dernières années.


Entrée (et sortie) du ramasse miettes.

Apple a fait un travail considérable pour moderniser sa plateforme de développement, y compris le remplacement complet de son compilateur, la remise à plat de son EDI (Environnement de développement Intégré), et en ajoutant des caractéristiques et une nouvelle syntaxe au langage Objective C lui-même.

Toutes ces choses là sont bonnes, mais aucune ne satisfait mes préoccupations spécifiques sur la gestion de mémoire. Apple s'est finalement résolue à rajouter le ramasse miettes à Objective C, mais ma crainte qu'Apple ne se soit pas réellement engagée pour le ramasse miettes dans objective C s'est révélée bien fondée. Aujourd'hui, des années après l'introduction de cette caractéristique, très peu d'applications d'Apple utilisent le ramasse miettes.

Il y a une bonne raison à cela. Le ramasse miettes à l'exécution s'applique mal, tout simplement, à Objective C. Pour sa simplicité syntaxique, et sa longue histoire couronnée de succès, le langage de programmation C est en réalité une bête étonnamment complexe, en particulier en ce qui concerne la gestion de mémoire. Sous C, tout ensemble de bits de taille pointer correctement aligné en mémoire peut être utilisé comme une adresse ; le langage autorise explicitement le passage de void * au type pointeur, et vice-versa. Obective C, en tant que sur-ensemble du C hérite de ces charmantes propriétés. En échange de ce sacrifice, le code d'objective C peut être compilé parallèlement à du vrai code C, et peut se lier facilement aux bibliothèques C.

Il semble avisé pour le ramasse miettes d'avoir une approche prudente à toute mémoire allouée en dehors de la communauté orientée objet limitée d'Objective C. Malheureusement, la mémoire allouée "à l'ancienne mode" dans le code C fait son chemin normalement dans le monde d'Objective C, et vice-versa. En théorie, tout ce genre de code pourrait être annoté de façon à ce que ça fonctionne correctement avec le ramasse miettes. Dans la pratique, Mac OS X contient beaucoup trop de code -la plus grande partie non écrite par Apple- pour un examen correct de chaque ligne, afin de s'assurer que le ramasse miettes a assez d'information à l'exécution pour prendre les bonnes décisions dans tous les cas. <:a>

Et de fait, en dépit des assurances d'Apple sur la faisabilité, il y a eu et il continue à y avoir des cas où même le code à l'intérieur des frameworks propres à Apple peut abuser le ramasse miettes d'Objective C. Ce genre de bogue est particulièrement insidieux, parce qu'elle peut se manifester seulement quand le ramasseur tourne depuis un certain temps. L'état de compatibilité du ramasse miettes pour les bibliothèques de tierces partie est encore plus désolant.

Pour faire court ; le ramasse miettes pour Objective C est hors jeu. (Il est encore supporté par Lion, mais je ne compterais pas sur Apple pour y investir un effort considérable susceptible de le remettre en selle). Et ne soyez pas surpris s'il prend le chemin de Rosetta dans quelques années. Pour le remplacer, Apple a créé quelque chose appelé Comptage de Référence Automatique ou ARC (Automated Reference Counting) en bref. Mais pour comprendre ARC, il vous faut d'abord comprendre comment la gestion de mémoire a traditionnellement fonctionné sous Cocoa.


La gestion de mémoire sous Cocoa

Cocoa utilise une technique de gestion de mémoire appelée le comptage de références. Chaque objet a un compte de références qui lui est associé. Quand un élément dans une application prend possession de l'objet, il incrémente le compte de références de l'objet en lui envoyant un message retain. Quand il a terminé avec l'objet, il décrémente le compte de références en envoyant à l'objet le message release. Quand le compte de références d'un objet est à zéro, il est désalloué.

Cela permet à un objet donné d'être utilisé par différents éléments de l'application, chacun d'eux étant responsable d'encadrer l'usage de l'objet par les messages retain et release. Si retain est envoyé à l'objet un plus grand nombre de fois que release, alors, le compte de références n'atteindra jamais zéro, et sa mémoire ne sera jamais libérée. Cela s'appelle une fuite de mémoire. Si release est envoyé un plus grand nombre de fois que retain, alors, un message release envoyé après que le compte de références a atteint zéro se retrouvera utilsant une région de la mémoire précédemment occupée par l'objet, qui peut maintenant contenir tout autre chose. Habituellement, il s'ensuit un crash.

Pour finir, il y a le message autorelease qui signifie "relâcher, mais plus tard". Quand un objet reçoit le message autorelease il est rajouté au "pool autorelease" courant. Quand ce pool est appelé, tous les objets qu'il contient reçoivent un message release pour chaque fois où ils ont été ajoutés au pool. (un objet peut être ajouté au même pool autorelease de multiples fois). Les applications Cocoa ont un pool autorelease qui est visité à la fin de chaque boucle d'évènements, mais de nouveaux pools peuvent être créée localement par le programmeur.

C'est simple, non ? Assurez-vous seulement que vos messages retain et release/autorelease sont équilibrés, et vous êtes bien. Mais, aussi simple que ce soit conceptuellement, il est en réalité étonnamment facile d'être pris en défaut. Les programmeurs Cocoa expérimentés vous diront que cette gestion de mémoire avec retain/release finit par devenir une seconde nature -et c'est le cas-, mais les programmeurs ne sont que des hommes. La traque précise du cycle de vie de tous les objets dans une grosse application commence à excéder les limites des capacités mentales de l'homme. Pour l'aider, Apple fournit des outils de développement sophistiqués pour traquer les allocations de mémoire et faire la chasse aux fuites.

Mais l'éducation et les outils ont une limite. Les experts Cocoa peuvent ne pas voir la gestion de mémoire avec retain/release comme une problème, mais Apple est tournée vers le futur, vers de nouveaux développeurs. Les autres plateformes mobiles ou de bureau n'exigent pas cette forme de gestion de mémoire manuelle dans leurs frameworks d'application de haut niveau. En se basant sur les efforts passés d'Apple pour le ramasse miettes, il semble évident qu'Apple croit que ce serait mieux pour la plateforme si les développeurs n'avaient pas à gérer la mémoire manuellement. Maintenant, en fin de compte, Apple croit avoir trouvé une solution sur laquelle elle peut vraiment se reposer.


L'entrée de ARC

Pour comprendre comment ARC fonctionne, commencez par vous représenter un fichier de code source traditionnel Objective C écrit par un programmeur Cocoa expert. Les messages retain, release et autorelease sont tous envoyés au bon endroit, et sont parfaitement équilibrés.

Maintenant, imaginez que vous éditez ce fichier de code source, en supprimant toute instance des messages retain, release et autorelease, et en changeant un seul réglage de construction dans XCode pour dire au compilateur d'incorporer tous les appels appropriés de gestion de mémoire dans le programme quand le code source est compilé. Voilà ARC. Comme son nom l'indique, c'est seulement un comptage de références traditionnel de Cocoa fait automatiquement.

figure

Les réglages d'ARC dans XCode (le renforcement est ajouté).

Avant d'expliquer comment ARC procède, il est important de comprendre ce que ne fait pas ARC. D'abord, ARC n'impose pas un nouveau modèle de mémoire à l'exécution. Le code compilé avec ARC utilise le même modèle de mémoire que celui du C normal, ou du code Objective C sans ARC, et peut être lié à toutes les mêmes bibliothèques. Ensuite, ARC fournit une gestion de mémoire automatique seulement pour les objets d'Objective C (notez cependant que les blocs se trouvent être aussi des objets Objective C sous le capot). La mémoire allouée de toute autre façon n'est pas affectée, et doit encore être gérée manuellement. (La même chose vaut pour les ressources comme les poignées sur les fichiers et les sockets). Enfin, ARC n'est pas du ramasse miettes. Il n'y a aucun processus qui parcourt l'image en mémoire d'une application en fonctionnement à la recherche de mémoire à désallouer. Tout de que fait ARC intervient au moment de la compilation.

Ce que fait ARC à la compilation n'est pas magique. Il n'y a pas d'intelligence artificielle élaborée là dedans. ARC n'utilise même pas l'analyseur statique sophistiqué de LLVM pour se représenter l'endroit où mettre les retains, et les releases. L'analyseur syntaxique prend beaucoup de temps, trop pour être un élément obligatoire d'un processus de construction ; il peut aussi produire des assertions fausses. Il est bien comme outil pour détecter de possibles bogues, mais une gestion de mémoire fiable exige la certitude.

Ce qui permet à ARC de fonctionner, est la même chose qui permet aux gens de devenir (occasionnellement) des programmeurs experts en Cocoa : les conventions. Cocoa a des règles sur le transfert de propriété qui interviennent lors d'opérations courantes comme la définition ou la récupération d'un attribut d'objet, l'initialisation d'un objet, ou l'obtention d'une copie mutable. En plus, les méthodes qui implémentent ces opérations suivent un ensemble de conventions de d'écriture. ARC connaît toutes ces règles, et les utilise pour décider quand il doit retenir (retain), et quand il doit relâcher (release)..

En fait, ARC suit ces règles d'un manière plus formaliste que ne le ferait un humain, en encadrant toute opération qui pourrait être influencée par la possession d'un objet avec des messages retain et release. Cela peut provoquer une énorme quantité d'opérations de gestion de mémoire. Heureusement, Apple dispose d'un excellent compilateur avec optimisation, appelé Clang (rebaptisé depuis en Apple LLVM Compiler 3.0 par les génies de marketing d'Apple). Clang parcourt cette mer de code généré mécaniquement , détecte et élimine les redondances jusqu'à ce que, ce qui reste ressemble beaucoup à ce qu'un humain aurait écrit.

Les conventions sont faites pour être contournées, bien sûr. Mais ce que ARC n'a pas en sophistication sémantique, il le rattrape en prédictibilité, et en vitesse, en vitesse, en vitesse. Dans les cas où l'homme est plus savant, on peut dire à ARC exactement quoi faire grâce à un ensemble étendu de nouveaux attributs et de macros qui permettent au développeur d'annoter des variables, des structures de données, des méthodes et des paramètres, avec des instructions explicites pour ARC. Mais l'idée derrière ARC est que les exceptions doivent être rares.

Pour s'assurer que ARC peut faire d'une façon correcte ce qu'il est sensé faire, quelques restrictions supplémentaires de langage ont été rajoutées. La plupart sont ésotériques, et interviennent aux limitres entre le code C normal et le code Objective C (par exemple, les struct et les unions C n'ont pas le droit de contenir des références à des objets Objective C). La compatibilité avec le code C existant est une des grandes forces d'Objective C. Mais comme ARC est une caractéristique qui fonctionne par unité de compilation, et que du code ARC et non-ARC peut être mélangé librement, ces nouvelles restrictions de langage rendent ARC plus fiable, sans compromettre l'inter-opérabilité.