web-dev-qa-db-fra.com

Comment fonctionne le nouveau mécanisme de comptage automatique des références?

Quelqu'un peut-il m'expliquer brièvement le fonctionnement d'ARC? Je sais que c'est différent de Garbage Collection, mais je me demandais comment cela fonctionnait.

De plus, si ARC fait ce que fait le GC sans nuire aux performances, pourquoi Java utilise-t-il le GC? Pourquoi n'utilise-t-il pas aussi bien ARC?

201
user635064

Chaque nouveau développeur qui vient à Objective-C doit apprendre les règles strictes du moment où il faut conserver, libérer et autorelease des objets. Ces règles spécifient même des conventions de dénomination qui impliquent le nombre de retenues d'objets renvoyés par des méthodes. La gestion de la mémoire dans Objective-C devient une seconde nature une fois que vous prenez à cœur ces règles et que vous les appliquez de manière cohérente, mais même les développeurs les plus expérimentés de Cocoa échouent de temps à autre.

Avec Clang Static Analyzer, les développeurs de LLVM ont compris que ces règles étaient suffisamment fiables pour pouvoir créer un outil permettant de signaler les fuites de mémoire et les libérations en excès dans les chemins empruntés par votre code.

Le comptage automatique des références (ARC) est la prochaine étape logique. Si le compilateur peut reconnaître où vous devez conserver et libérer des objets, pourquoi ne pas le faire insérer ce code pour vous? Les compilateurs et leurs frères sont doués pour des tâches rigides et répétitives. Les humains oublient des choses et font des erreurs, mais les ordinateurs sont beaucoup plus cohérents.

Cependant, cela ne vous libère pas complètement de la gestion de la mémoire sur ces plates-formes. Je décris le problème principal à surveiller (conserver les cycles) dans ma réponse ici , ce qui peut nécessiter un peu de réflexion de votre part pour marquer les points faibles. Cependant, c'est mineur par rapport à ce que vous gagnez dans ARC.

Comparé à la gestion manuelle de la mémoire et à la récupération de place, ARC vous offre le meilleur des deux mondes en éliminant le besoin d'écrire du code de conservation/libération, sans avoir les profils de mémoire en pause et en dents de scie vus dans un environnement de récupération. Les seuls avantages de la récupération de place par rapport à cela sont sa capacité à gérer les cycles de conservation et le fait que les affectations de propriétés atomiques sont peu coûteuses (comme indiqué ci-dessous ici ). Je sais que je remplace tout mon code Mac GC existant par des implémentations ARC.

Quant à savoir si cela pourrait être étendu à d'autres langues, cela semble être axé sur le système de comptage de références en Objective-C. Cela pourrait être difficile à appliquer à Java ou à d'autres langages, mais je ne connais pas suffisamment les détails du compilateur de bas niveau pour pouvoir faire une déclaration définitive. Étant donné que c’est Apple qui pousse ces efforts dans LLVM, Objective-C sera prioritaire, sauf si une autre partie y consacre d’importantes ressources.

La révélation de cette surprise aux développeurs de WWDC, de sorte que les gens n'étaient pas conscients que quelque chose comme cela pourrait être fait. Il peut apparaître sur d'autres plateformes au fil du temps, mais pour l'instant, il est exclusif à LLVM et à Objective-C.

241
Brad Larson

ARC ne fait que lire l’ancien programme Retenir/Libérer (MRC), le compilateur déterminant quand appeler/Retenir. Il aura tendance à être plus performant, à utiliser moins de mémoire de pointe et à des performances plus prévisibles qu’un système de CPG.

D'autre part, certains types de structure de données ne sont pas possibles avec ARC (ou MRC), alors que GC peut les gérer.

Par exemple, si vous avez une classe nommée noeud et que noeud a un tableau NSArray d'enfants et une référence unique à son parent qui "ne fonctionne que" avec GC. Avec ARC (et le comptage manuel des références), vous avez un problème. Tout nœud donné sera référencé à partir de ses enfants et également de son parent.

Comme:

A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A

Tout va bien pendant que vous utilisez A (par exemple via une variable locale).

Une fois que vous avez terminé (et B1/B2/B3), un système CPG décidera éventuellement de regarder tout ce qu'il peut trouver en commençant par les registres de la pile et de la CPU. Il ne trouvera jamais A, B1, B2, B3, il les finalisera et recyclera la mémoire dans d'autres objets.

Lorsque vous utilisez ARC ou MRC et que vous terminez avec A, le nombre de références correspondant est 3 (B1, B2 et B3 le référencent tous), et B1/B2/B3 aura le nombre de références égal à 1 (le tableau NSArray de A contient une référence à chaque). Ainsi, tous ces objets restent vivants même si rien ne peut les utiliser.

La solution commune est de décider que l’une de ces références doit être faible (ne pas contribuer au décompte des références). Cela fonctionnera pour certains modèles d'utilisation, par exemple si vous faites référence à B1/B2/B3 uniquement via A. Cependant, dans d'autres modèles, cela échoue. Par exemple, si vous gardez parfois B1 et que vous vous attendez à remonter via le pointeur parent et trouvez A. Avec une référence faible si vous ne tenez que sur B1, A peut (et va normalement) s’évaporer et prendre B2 et B3. avec ça.

Parfois, ce n’est pas un problème, mais certaines méthodes très utiles et naturelles de travailler avec des structures de données complexes sont très difficiles à utiliser avec ARC/MRC.

Donc, ARC cible le même type de problèmes que les cibles du GC. Cependant, ARC fonctionne sur un ensemble de modèles d'utilisation plus limité que GC, donc si vous utilisiez un langage GC (comme Java) et y greffiez quelque chose comme ARC, certains programmes ne fonctionneraient plus (ou du moins généreraient des tonnes de mémoire abandonnée. et peut causer de graves problèmes d’échange ou un manque de mémoire ou d’espace de permutation).

Vous pouvez également dire qu'ARC accorde une plus grande priorité aux performances (ou peut-être à la prévisibilité), tandis que le GC accorde une plus grande priorité à une solution générique. En conséquence, le GC a des exigences moins prévisibles en termes de ressources processeur/mémoire et de performances inférieures (normalement) à celles d'ARC, mais peut gérer n'importe quel modèle d'utilisation. ARC fonctionnera beaucoup mieux pour de nombreux modèles d'utilisation courants, mais pour quelques modèles d'utilisation (valables!), Il tombera et mourra.

22
Stripes

La magie

Mais plus spécifiquement, ARC fonctionne en faisant exactement ce que vous feriez avec votre code (avec certaines différences mineures). ARC est une technologie de compilation, contrairement au GC, qui est un environnement d'exécution et aura un impact négatif sur vos performances. ARC suivra les références aux objets pour vous et synthétisera les méthodes de retenue/libération/libération automatique selon les règles normales. A cause de cela, l'ARC peut également libérer des objets dès qu'ils ne sont plus nécessaires, plutôt que de les jeter dans un pool autorelease dans un but purement conventionnel.

Parmi les autres améliorations, citons la mise à zéro des références faibles, la copie automatique des blocs dans le tas, les accélérations généralisées (6x pour les pools à relâchement automatique!).

Une discussion plus détaillée sur le fonctionnement de tout cela se trouve dans LLVM Docs on ARC.

4
Joshua Weinberg

Cela varie énormément du ramassage des ordures. Avez-vous vu les avertissements vous indiquant que des objets peuvent couler sur différentes lignes? Ces déclarations vous indiquent même sur quelle ligne vous avez attribué l'objet. Cela a été poussé plus loin et permet maintenant d'insérer des instructions retain/release aux emplacements appropriés, mieux que la plupart des programmeurs, presque 100% du temps. De temps en temps, vous avez besoin de quelques exemples étranges d'objets conservés pour vous aider.

3
FreeAsInBeer

ARC est une fonction de compilateur permettant la gestion automatique de la mémoire des objets.

Au lieu de devoir vous rappeler quand utiliser retain, release et autorelease, ARC évalue les exigences de durée de vie de vos objets et insère automatiquement les appels de gestion de la mémoire appropriés pour vous au moment de la compilation. Le compilateur génère également des méthodes dealloc appropriées pour vous.

Le compilateur insère les appels retain/release nécessaires à la compilation, mais ces appels sont exécutés à l'exécution, comme n'importe quel autre code.

Le diagramme suivant vous donnerait une meilleure compréhension du fonctionnement d’ARC.

enter image description here

Ceux qui sont nouveaux dans le développement iOS et qui n’ont pas d’expérience professionnelle avec Objective C. Veuillez vous reporter à la documentation d’Apple pour Guide de programmation de la gestion de la mémoire avancée pour une meilleure compréhension de la gestion de la mémoire.

0
Yogesh Bharate

Très bien expliqué par la documentation du développeur Apple. Lire "Comment fonctionne ARC"

Pour vous assurer que les instances ne disparaissent pas tant qu’elles sont toujours nécessaires, ARC suit le nombre de propriétés, de constantes et de variables faisant actuellement référence à chaque instance de classe. ARC ne désallouera pas d'instance tant qu'il existe au moins une référence active vers cette instance.

Pour vous assurer que les instances ne disparaissent pas tant qu’elles sont toujours nécessaires, ARC suit le nombre de propriétés, de constantes et de variables faisant actuellement référence à chaque instance de classe. ARC ne désallouera pas d'instance tant qu'il existe au moins une référence active vers cette instance.

Pour connaître Diff. entre la collecte des ordures et ARC: lire ceci

0
Lalit Kumar