À ARC ou pas à ARC? Quels sont les avantages et inconvénients? [fermé]

113

Je n'ai pas encore utilisé ARC, car la majorité du code du projet sur lequel je travaille actuellement a été écrit avant iOS 5.0.

Je me demandais simplement si la commodité de ne pas conserver / publier manuellement (et probablement un code plus fiable qui en résulte?) L'emporte-t-elle sur le `` coût '' de l'utilisation d'ARC? Quelles sont vos expériences d'ARC, et le recommanderiez-vous?

Alors:

  • Quel avantage l'ARC peut-il apporter à un projet?
  • ARC a-t-il un coût comme le ramassage des ordures en Java?
  • Avez-vous utilisé ARC et si oui, comment l'avez-vous trouvé jusqu'à présent?
Simon Withington
la source
Il n'y a pas de garbage collection sur ipad / ios. Parlez-vous d'OS X?
dasblinkenlight
1
Mes excuses, j'utilise des termes Java déplacés. Je veux dire qu'avec ARC, les objets peuvent être conservés en mémoire plus longtemps que nécessaire, puis libérés en tant que groupe dans un pool à libération automatique quelque temps plus tard. C'est cet effet de leur conservation et de leur libération avec d'autres objets plus tard, de la même manière que le ramasse-miettes de Java auquel je fais référence.
Simon Withington
3
@TenementFunster, pour le même code (moins les appels à la libération), ARC ne maintiendra l'objet que du code non-ARC. En fait, il le publiera souvent plus tôt que vous ne l'auriez fait. Il y a un petit nombre de choses qui sont un peu plus lentes, mais elles ont tellement accéléré les modèles courants que cela éclipse l'impact sur les performances. Pour de nombreux modèles courants (conserver un objet qui a été renvoyé avec une libération automatique par exemple), vous ne pouvez littéralement pas l'écrire à la main aussi vite qu'ARC le fera automatiquement.
Rob Napier
1
En ce qui concerne le garbage collection, consultez ma réponse à cette question similaire: Quelle est la différence entre le comptage automatique de références Objective-C et le garbage collection?
Brad Larson

Réponses:

147

Il n'y a aucun inconvénient. Utilise le. Fais-le aujourd'hui. C'est plus rapide que votre ancien code. C'est plus sûr que votre ancien code. C'est plus facile que votre ancien code. Ce n'est pas un ramassage des ordures. Il n'a pas de surcharge d'exécution du GC. Les inserts du compilateur conservent et publient dans tous les endroits que vous devriez avoir de toute façon. Mais il est plus intelligent que vous et peut optimiser ceux qui ne sont pas réellement nécessaires (tout comme il peut dérouler des boucles, éliminer des variables temporaires, des fonctions en ligne, etc.)

OK, maintenant je vais vous parler des petits inconvénients:

  • Si vous êtes un développeur ObjC de longue date, vous vous contracterez pendant environ une semaine lorsque vous verrez du code ARC. Vous vous en remettrez très vite.

  • Il y a quelques (très) petites complications dans le pontage vers le code Core Foundation. Il y a un peu plus de complications dans le traitement de tout ce qui traite un idcomme void*. Des choses comme les tableaux C de idpeuvent prendre un peu plus de réflexion pour faire correctement. Une manipulation sophistiquée d'ObjC va_argspeut également causer des problèmes. La plupart des choses impliquant des mathématiques sur un pointeur ObjC sont plus délicates. Vous ne devriez pas en avoir beaucoup de toute façon.

  • Vous ne pouvez pas mettre un iddans un struct. C'est assez rare, mais parfois utilisé pour emballer des données.

  • Si vous n'avez pas suivi la dénomination KVC correcte et que vous mélangez du code ARC et non-ARC, vous aurez des problèmes de mémoire. ARC utilise la dénomination KVC pour prendre des décisions sur la gestion de la mémoire. Si c'est tout du code ARC, alors cela n'a pas d'importance car il fera le même "mal" des deux côtés. Mais s'il s'agit d'un mélange ARC / non-ARC, il y a une discordance.

  • ARC perdra de la mémoire lors des levées d'exceptions ObjC. Une exception ObjC doit être très proche de la fin de votre programme. Si vous détectez un nombre important d'exceptions ObjC, vous les utilisez de manière incorrecte. Ceci peut être corrigé en utilisant -fobjc-arc-exceptions, mais il encourt les pénalités décrites ci-dessous:

  • ARC ne perdra pas de mémoire pendant les levées d'exceptions ObjC ou C ++ dans le code ObjC ++, mais cela se fait au détriment des performances en termes de temps et d'espace. Ceci est encore une autre parmi une longue liste de raisons pour minimiser votre utilisation d'ObjC ++.

  • ARC ne fonctionnera pas du tout sur iPhoneOS 3 ou Mac OS X 10.5 ou version antérieure. (Cela m'empêche d'utiliser ARC dans de nombreux projets.)

  • __weakles pointeurs ne fonctionnent pas correctement sur iOS 4 ou Mac OS X 10.6, ce qui est dommage, mais assez facile à contourner. __weakLes pointeurs sont excellents, mais ils ne sont pas le principal argument de vente d'ARC.

Pour plus de 95% du code, ARC est génial et il n'y a aucune raison de l'éviter (à condition que vous puissiez gérer les restrictions de version du système d'exploitation). Pour le code non ARC, vous pouvez transmettre -fno-objc-arcfichier par fichier. Xcode rend malheureusement cela beaucoup plus difficile qu'il ne devrait l'être en pratique. Vous devriez probablement déplacer le code non-ARC dans un xcodeproj séparé pour simplifier cela.

En conclusion, passez à ARC dès que vous le pouvez et ne regardez jamais en arrière.


ÉDITER

J'ai vu quelques commentaires du genre "l'utilisation d'ARC ne remplace pas la connaissance des règles de gestion de la mémoire Cocoa." C'est généralement vrai, mais il est important de comprendre pourquoi et pourquoi pas. Premièrement, si tout votre code utilise ARC et que vous enfreignez les trois mots magiquespartout, vous n'aurez toujours aucun problème. Choquant à dire, mais voilà. ARC peut conserver certaines choses que vous ne vouliez pas conserver, mais il les libérera également, donc cela n'aura jamais d'importance. Si j'enseignais une nouvelle classe à Cocoa aujourd'hui, je ne passerais probablement pas plus de cinq minutes sur les règles de gestion de la mémoire, et je ne mentionnerais probablement que les règles de dénomination de la gestion de la mémoire lors de la discussion de la dénomination KVC. Avec ARC, je crois que vous pourriez devenir un programmeur débutant décent sans apprendre du tout les règles de gestion de la mémoire.

Mais vous ne pouvez pas devenir un programmeur intermédiaire décent. Vous devez connaître les règles pour établir correctement le lien avec Core Foundation, et chaque programmeur intermédiaire doit traiter avec CF à un moment donné. Et vous devez connaître les règles du code mixte ARC / MRC. Et vous devez connaître les règles lorsque vous commencez à jouer avec des void*pointeurs id(dont vous continuez à avoir besoin pour exécuter correctement KVO). Et les blocs ... eh bien, la gestion de la mémoire par blocs est juste bizarre.

Donc, mon point est que la gestion de la mémoire sous-jacente est toujours importante, mais là où je passais beaucoup de temps à énoncer et à reformuler les règles pour les nouveaux programmeurs, avec ARC, cela devient un sujet plus avancé. Je préfère amener les nouveaux développeurs à penser en termes de graphes d'objets plutôt que de se remplir la tête avec les appels sous-jacents à objc_retain().

Rob Napier
la source
3
Une chose à laquelle il faut faire très attention (en non-ARC également, mais plus en ARC parce que c'est tellement invisible maintenant) est de conserver les cycles. Mon conseil ici est 1) si vous vous trouvez en train de stocker un bloc objc en tant que variable d'instance, examinez-le longuement pour voir s'il pourrait capturer l'objet dont il est un ivar, même indirectement. 2) Concevez en fait votre graphe d'objets, plutôt que de simplement le laisser se produire. Vous devez savoir ce qui possède et si vous voulez écrire du bon code. 3) Utilisez des photos: friday.com/bbum/2010/10/17/…
Catfish_Man
1
@Catfish_Man Tous les bons points. Les boucles de rétention ont toujours été un problème. Le nouveau conseil d'Apple est exactement comme vous le dites dans le n ° 2. Nous devons penser aux graphes d'objets plutôt que de les conserver et de les libérer. Le n ° 1 est un problème sérieux avec les blocs, et l'une des nombreuses raisons pour lesquelles je trouve que les blocs sont une bénédiction mitigée qui doit être abordée avec prudence.
Rob Napier
2
Il y a un inconvénient sérieux qui n'a pas été mentionné: la compatibilité croisée. Pour nous, âmes courageuses et insensées qui font face aux friches connues sous le nom de programmation multiplateforme, ARC n'est tout simplement pas une option, du moins pas avant que GNU ne développe à nouveau ses fonctionnalités d'exécution et de compilateur ObjC (ils disent que plus est en route).
Lapin
2
Vous pouvez utiliser ARC, sauf que vous devez prendre en charge les appareils iOS 3.x. BTW, assurez-vous d'utiliser Xcode pour effectuer la transition (Edition> Refactoriser> Convertir en Objective-C ARC). Pendant le processus, Xcode ferait beaucoup de validation pour s'assurer que votre code fonctionnerait et identifierait tous les codes qui enfreignent ces directives de conception.
ZhangChn
1
Excellent .. réponse ponctuelle. c'est 100e de moi. Félicitations pour un siècle;)
Ajay Sharma
20

De meilleures réponses plus techniques que les miennes viendront, mais voici:

  • ARC! = Ramasse-miettes. Il n'y a pas de pénalité d'exécution, c'est fait au moment de la compilation.
  • ARC aussi! = Il suffit de tout libérer automatiquement, comme vous le suggérez dans votre commentaire. Lire la documentation
  • Il est génial une fois que vous réalisez combien la gestion beaucoup de manuel de référence que vous étiez en train de faire
  • Utilise le!
  • Un inconvénient - maintenir un ancien code sans arc devient soudainement très fastidieux.
jrturton
la source
Oui, c'est pourquoi je ne l'ai pas utilisé jusqu'à présent - je ne suis pas sûr de pouvoir supporter de parcourir notre quantité substantielle de code préexistant pour le convertir ... Je vais certainement l'essayer dans le prochain projet. Merci pour votre réponse :)
Simon Withington
Ce n'est pas que maintenir l'ancien code devienne plus difficile, c'est que vos attentes ont changé. Il n'est donc pas vraiment juste de blâmer l'ARC pour avoir rendu la vie plus facile. Xcode facilite la conversion de votre ancien code en ARC lorsque vous êtes prêt, mais vous ne pouvez évidemment pas l'utiliser si vous devez toujours prendre en charge les anciennes versions d'iOS.
Caleb
1
@Caleb Je ne blâmais pas ARC, c'est juste le seul inconvénient que j'ai vu jusqu'à présent - ça m'a gâté pourri dans l'espace d'un seul projet.
jrturton
Ouais; Je n'ai pas mentionné cela comme un problème, mais il y a un petit problème pour sortir de la pratique de la gestion de la mémoire lorsque vous devez basculer entre les bases de code. Certains de mes projets fonctionnent sur 10.4, donc je fais encore beaucoup de travail d'Objective-C 1.0 (donc pas de @synthesize, encore moins d'ARC). Mais on s'habitue assez bien à changer de mode.
Rob Napier
@jrturton J'aurais dû dire plus clairement que j'ai écrit cela pour le bénéfice de l'OP et des futurs lecteurs qui pourraient ne pas comprendre ce que fait ARC. Je sais exactement ce que vous voulez dire, je ne voulais tout simplement pas que quiconque tire la conclusion erronée que le mélange de code ARC et non-ARC crée un problème.
Caleb
16

Quel avantage l'ARC peut-il apporter à un projet?

L'avantage est un degré significatif de protection contre les erreurs courantes de gestion de la mémoire. Les fuites causées par l'échec de la libération d'un objet et les plantages dus à l'absence de rétention ou à la libération prématurée d'un objet doivent être considérablement réduites. Vous devez toujours comprendre le modèle de mémoire compté par référence afin de pouvoir classer vos références comme fortes ou faibles, éviter les cycles de rétention, etc.

Combien coûte réellement le ramassage des ordures?

Il n'y a pas de garbage collection dans iOS. ARC est similaire à GC en ce sens que vous n'avez pas à conserver ou à libérer manuellement les objets. C'est différent de GC en ce qu'il n'y a pas de ramasse-miettes. Le modèle de conservation / publication s'applique toujours, c'est juste que le compilateur insère les appels de gestion de mémoire appropriés dans votre code pour vous au moment de la compilation.

Avez-vous utilisé ARC et si oui, comment l'avez-vous trouvé jusqu'à présent?

C'est un peu déconcertant si vous êtes habitué au comptage de références, mais c'est juste une question de s'y habituer et d'apprendre à avoir confiance que le compilateur fera vraiment ce qu'il faut. Cela ressemble à une continuation du changement des propriétés fourni avec Objective-C 2.0, qui était un autre grand pas en avant vers la simplification de la gestion de la mémoire. Sans les appels manuels de gestion de la mémoire, votre code devient un peu plus court et plus facile à lire.

Le seul problème avec ARC est qu'il n'est pas pris en charge dans les anciennes versions d'iOS, vous devez donc en tenir compte avant de décider de l'adopter.

Caleb
la source
1
Il y a la meilleure réponse dont je parlais!
jrturton
1
Ouais, bonne réponse. N'y a-t-il donc pas vraiment d'inconvénient à ARC en dehors du fait qu'il faut apprendre à avoir confiance que cela fonctionne? Cela semble trop beau pour être vrai dans ce cas?
Simon Withington le
4

Je pense que l'ARC est une excellente idée. Par rapport à GC, vous pouvez avoir votre gâteau et le manger aussi. J'ai tendance à croire que MRC impose une «discipline» inestimable à la gestion de la mémoire que tout le monde gagnerait à avoir. Mais je conviens également que le vrai problème à prendre en compte est la propriété des objets et les graphiques d'objets (comme beaucoup l'ont souligné), et non le nombre de références de bas niveau en soi.

Pour conclure: ARC n'est PAS un laissez-passer gratuit pour ne pas penser à la mémoire; c'est un outil pour aider les humains à éviter les tâches répétitives, qui causent du stress et sont sujettes aux erreurs, donc mieux déléguées à une machine (le compilateur, dans ce cas).

Cela dit, je suis personnellement un peu un artisan et je n'ai pas encore fait la transition. Je viens de commencer à utiliser Git ...

MISE À JOUR: J'ai donc migré tout mon jeu, bibliothèque gl incluse, et aucun problème jusqu'à présent (sauf avec l'assistant de migration dans Xcode 4.2). Si vous démarrez un nouveau projet, allez-y.

Nicolas Miari
la source
2

Je l'ai utilisé dans quelques projets (certes petits), et je n'ai que de bonnes expériences, à la fois en termes de performances et de fiabilité.

Une petite mise en garde est que vous devez apprendre les choses à faire et à ne pas faire: les références faibles pour ne pas provoquer de boucles de référence si vous codez votre interface utilisateur par vous-même, le concepteur a tendance à faire du bon travail. automatiquement si vous configurez votre interface graphique en l'utilisant.

Joachim Isaksson
la source
2

Le seul inconvénient que j'ai rencontré est si vous utilisez une bibliothèque avec beaucoup de fonctions et de données CoreFoundation. Dans MRC, vous n'aviez pas à vous soucier d'utiliser un CFStringRefau lieu d'un NSString*. Dans ARC, vous devez spécifier comment les deux interagissent (pont de base? Libérer l'objet CoreFoundation et le déplacer vers ARC? Créer un objet Cocoa en tant qu'objet conservé +1 CoreFoundation?) De plus, sous OS X, il n'est disponible que sur 64- code de bit (bien que j'aie un en-tête qui fonctionne autour de ça…).

MaddTheSane
la source