Zu ARC oder nicht zu ARC? Was sind die Vor- und Nachteile? [geschlossen]

113

Ich habe ARC noch nicht verwendet, da der Großteil des Codes in dem Projekt, an dem ich gerade arbeite, vor iOS 5.0 geschrieben wurde.

Ich habe mich nur gefragt, ob die Bequemlichkeit, nicht manuell zu behalten / freizugeben (und vermutlich zuverlässigerer Code, der sich daraus ergibt?) Die Kosten für die Verwendung von ARC überwiegt. Welche Erfahrungen haben Sie mit ARC gemacht und würden Sie es empfehlen?

So:

  • Wie viel Nutzen kann ARC für ein Projekt bringen?
  • Hat ARC Kosten wie Garbage Collection in Java?
  • Haben Sie ARC verwendet und wenn ja, wie haben Sie es bisher gefunden?
Simon Withington
quelle
Auf ipad / ios gibt es keine Speicherbereinigung. Sprechen Sie über OS X?
Dasblinkenlight
1
Ich entschuldige mich dafür, dass ich Java-Begriffe nicht richtig verwende. Ich meine, mit ARC können Objekte länger als nötig im Speicher gehalten und einige Zeit später als Gruppe in einem Pool für automatische Freigabe freigegeben werden. Es ist dieser Effekt, dass sie später mit anderen Objekten aufbewahrt und freigegeben werden, ähnlich wie bei Javas Garbage Collection, auf die ich mich beziehe.
Simon Withington
3
@TenementFunster, für denselben Code (abzüglich der freizugebenden Aufrufe) hält ARC das Objekt nicht länger als Nicht-ARC-Code herum. Tatsächlich wird es oft früher veröffentlicht, als Sie es hätten. Es gibt eine kleine Anzahl von Dingen, die etwas langsamer sind, aber sie beschleunigen die gängigen Muster so sehr, dass sie die Auswirkungen auf die Leistung in den Schatten stellen. Bei vielen gängigen Mustern (z. B. Beibehalten eines Objekts, das mit einer Autorelease zurückgegeben wurde) können Sie es buchstäblich nicht so schnell von Hand schreiben, wie ARC dies automatisch tut.
Rob Napier
1
Bezüglich der Speicherbereinigung siehe meine Antwort auf diese ähnliche Frage: Was ist der Unterschied zwischen der automatischen Referenzzählung von Objective-C und der Speicherbereinigung?
Brad Larson

Antworten:

147

Es gibt keinen Nachteil. Benutze es. Mach es heute. Es ist schneller als Ihr alter Code. Es ist sicherer als Ihr alter Code. Es ist einfacher als Ihr alter Code. Es ist keine Speicherbereinigung. Es hat keinen GC-Laufzeitaufwand. Die Compiler-Einfügungen behalten und geben sie an allen Stellen frei, die Sie sowieso haben sollten. Aber es ist schlauer als Sie und kann diejenigen optimieren, die nicht wirklich benötigt werden (genau wie es Schleifen abrollen, temporäre Variablen, Inline-Funktionen usw. eliminieren kann).

OK, jetzt erzähle ich Ihnen von den kleinen Nachteilen:

  • Wenn Sie ein langjähriger ObjC-Entwickler sind, werden Sie ungefähr eine Woche lang zucken, wenn Sie ARC-Code sehen. Sie werden sehr schnell darüber hinwegkommen.

  • Es gibt einige (sehr) kleine Komplikationen bei der Überbrückung zum Core Foundation-Code. Es gibt etwas mehr Komplikationen im Umgang mit allem, was ein idals behandelt void*. Dinge wie C-Arrays von idkönnen etwas mehr Nachdenken erfordern, um richtig zu machen. Ein ausgefallener Umgang mit ObjC va_argskann ebenfalls Probleme verursachen. Die meisten Dinge, die Mathematik auf einem ObjC-Zeiger betreffen, sind schwieriger. Sie sollten auf keinen Fall viel davon haben.

  • Sie können kein idin ein setzen struct. Dies ist ziemlich selten, wird aber manchmal zum Packen von Daten verwendet.

  • Wenn Sie die korrekte KVC-Benennung nicht befolgt und ARC- und Nicht-ARC-Code gemischt haben, treten Speicherprobleme auf. ARC verwendet die KVC-Benennung, um Entscheidungen über die Speicherverwaltung zu treffen. Wenn es nur ARC-Code ist, spielt es keine Rolle, da es auf beiden Seiten das gleiche "Falsche" macht. Wenn es sich jedoch um gemischtes ARC / Nicht-ARC handelt, liegt eine Nichtübereinstimmung vor.

  • ARC verliert während der Auslösung von ObjC-Ausnahmen Speicher. Eine ObjC-Ausnahme sollte sehr nahe an der Beendigung Ihres Programms liegen. Wenn Sie eine erhebliche Anzahl von ObjC-Ausnahmen abfangen, verwenden Sie diese falsch. Dies kann mit behoben werden -fobjc-arc-exceptions, führt jedoch zu den unten beschriebenen Strafen:

  • ARC verliert während der Auslösung von ObjC- oder C ++ - Ausnahmen im ObjC ++ - Code keinen Speicher, dies geht jedoch zu Lasten der Zeit- und Raumleistung. Dies ist ein weiterer Grund in einer langen Liste von Gründen, die Verwendung von ObjC ++ zu minimieren.

  • ARC funktioniert unter iPhoneOS 3 oder Mac OS X 10.5 oder früher überhaupt nicht. (Dies hindert mich daran, ARC in vielen Projekten zu verwenden.)

  • __weakZeiger funktionieren unter iOS 4 oder Mac OS X 10.6 nicht richtig, was schade ist, aber ziemlich einfach zu umgehen ist. __weakZeiger sind großartig, aber sie sind nicht das Hauptverkaufsargument von ARC.

Für mehr als 95% des Codes ist ARC brillant und es gibt überhaupt keinen Grund, dies zu vermeiden (vorausgesetzt, Sie können mit den Einschränkungen der Betriebssystemversion umgehen). Für Nicht-ARC-Code können Sie übergeben-fno-objc-arc Datei für Datei weitergeben. Xcode macht dies leider viel schwieriger als es in der Praxis sein sollte. Sie sollten wahrscheinlich Nicht-ARC-Code in ein separates xcodeproj verschieben, um dies zu vereinfachen.

Wechseln Sie abschließend so schnell wie möglich zu ARC und schauen Sie niemals zurück.


BEARBEITEN

Ich habe einige Kommentare im Sinne von "Die Verwendung von ARC ist kein Ersatz für die Kenntnis der Cocoa-Speicherverwaltungsregeln" gesehen. Dies ist meistens wahr, aber es ist wichtig zu verstehen, warum und warum nicht. Erstens, wenn Ihr gesamter Code ARC verwendet und Sie die drei magischen Wörter verletzen überall gegen den , haben Sie immer noch keine Probleme. Schockierend zu sagen, aber los geht's. ARC behält möglicherweise einige Dinge bei, die Sie nicht beibehalten möchten, aber es gibt sie auch frei, sodass es keine Rolle spielt. Wenn ich heute eine neue Klasse in Cocoa unterrichten würde, würde ich wahrscheinlich nicht mehr als fünf Minuten mit den eigentlichen Speicherverwaltungsregeln verbringen, und ich würde wahrscheinlich nur die Speicherverwaltungs-Namensregeln erwähnen, während ich über die KVC-Benennung diskutiere. Mit ARC,

Aber Sie könnten kein anständiger fortgeschrittener Programmierer werden. Sie müssen die Regeln kennen, um eine korrekte Verbindung mit Core Foundation herzustellen, und jeder fortgeschrittene Programmierer muss sich irgendwann mit CF befassen. Und Sie müssen die Regeln für gemischten ARC / MRC-Code kennen. Und Sie müssen die Regeln kennen, wenn Sie anfangen, mit void*Zeigern herumzuspielen id(die Sie weiterhin benötigen, um KVO korrekt auszuführen). Und Blöcke ... nun, Blockspeicherverwaltung ist einfach komisch.

Mein Punkt ist also, dass die zugrunde liegende Speicherverwaltung immer noch wichtig ist, aber wo ich früher viel Zeit damit verbracht habe, die Regeln für neue Programmierer festzulegen und neu zu formulieren, wird ARC mit ARC zu einem fortgeschritteneren Thema. Ich möchte lieber neue Entwickler dazu bringen, in Objektgraphen zu denken, als ihre Köpfe mit den zugrunde liegenden Aufrufen zu füllen objc_retain().

Rob Napier
quelle
3
Eine Sache, auf die Sie sehr achten sollten (auch bei Nicht-ARC, aber mehr bei ARC, weil es jetzt so unsichtbar ist), ist das Beibehalten von Zyklen. Mein Rat hier ist 1) Wenn Sie feststellen, dass Sie einen Objektblock als Instanzvariable speichern, schauen Sie ihn sich genau an, um zu sehen, ob er das Objekt erfassen kann, von dem er selbst indirekt ist. 2) Entwerfen Sie Ihr Objektdiagramm tatsächlich, anstatt es nur passieren zu lassen. Sie müssen wissen, was was besitzt, wenn Sie guten Code schreiben möchten. 3) Verwenden Sie Heapshots: friday.com/bbum/2010/10/17/…
Catfish_Man
1
@Catfish_Man Alle guten Punkte. Retain-Loops waren schon immer ein Problem. Apples neuer Rat ist genau so, wie Sie es in # 2 sagen. Wir müssen über Objektgraphen nachdenken, anstatt sie beizubehalten und freizugeben. # 1 ist ein ernstes Problem mit Blöcken, und einer von mehreren Gründen, warum ich Blöcke als gemischten Segen empfinde, sollte mit Vorsicht angegangen werden.
Rob Napier
2
Es gibt einen schwerwiegenden Nachteil, der nicht erwähnt wurde: Kreuzkompatibilität. Für uns mutige und dumme Seelen, die sich den als plattformübergreifende Programmierung bekannten Ödlanden gegenübersehen, ist ARC einfach keine Option, zumindest nicht, bis GNU ihre ObjC-Laufzeit- und Compilerfunktionen erneut erweitert (sie sagen, dass weitere auf dem Weg sind).
Kaninchen
2
Sie können ARC verwenden, außer dass Sie iOS 3.x-Geräte unterstützen müssen. Stellen Sie übrigens sicher, dass Sie Xcode für den Übergang verwenden (Bearbeiten> Refactor> In Objective-C ARC konvertieren). Während des Prozesses hat Xcode viele Überprüfungen durchgeführt, um sicherzustellen, dass Ihr Code funktioniert, und um alle Codes herauszufinden, die gegen diese Entwurfsrichtlinien verstoßen.
ZhangChn
1
Ausgezeichnet .. antworte mit punktuell. Das ist der 100. von mir. Herzlichen Glückwunsch für ein Jahrhundert;)
Ajay Sharma
20

Bessere, technischere Antworten als meine werden kommen, aber hier ist:

  • ARC! = Speicherbereinigung. Es gibt keine Laufzeitstrafe, sie erfolgt zur Kompilierungszeit.
  • ARC also! = Einfach alles automatisch freigeben, wie Sie in Ihrem Kommentar vorschlagen. Lesen Sie die Dokumente
  • Es ist fantastisch , wenn Sie erkennen , wie viel manuelle Literaturverwaltung Sie wurden zu tun
  • Benutze es!
  • Ein Nachteil: Das Verwalten von altem Nicht-Bogen-Code wird plötzlich sehr mühsam.
jrturton
quelle
Ja, deshalb habe ich es bisher nicht verwendet - ich bin mir nicht sicher, ob ich es ertragen könnte, unsere beträchtliche Menge an bereits vorhandenem Code durchzugehen, um es zu konvertieren ... Ich werde es aber auf jeden Fall im nächsten Projekt ausprobieren. Vielen Dank für Ihre Antwort :)
Simon Withington
Es ist nicht so, dass die Pflege von altem Code schwieriger wird, sondern dass sich Ihre Erwartungen geändert haben. Es ist also nicht wirklich fair, ARC dafür verantwortlich zu machen, dass es das Leben leichter macht. Mit Xcode können Sie Ihren alten Code problemlos in ARC konvertieren, wenn Sie bereit sind. Sie können ihn jedoch offensichtlich nicht verwenden, wenn Sie noch ältere iOS-Versionen unterstützen müssen.
Caleb
1
@Caleb Ich habe ARC nicht beschuldigt, es ist nur der einzige Nachteil, den ich bisher gesehen habe - es hat mich im Rahmen eines einzelnen Projekts verdorben.
Jrturton
Ja; Ich habe das nicht als Problem aufgeführt, aber es gibt ein kleines Problem beim Verlassen der Speicherverwaltungspraxis, wenn Sie zwischen Codebasen wechseln müssen. Einige meiner Projekte laufen auf 10.4, daher arbeite ich immer noch viel mit Objective-C 1.0 (also kein @synthesize, geschweige denn ARC). Aber man gewöhnt sich ziemlich gut daran, den Modus zu wechseln.
Rob Napier
@jrturton Ich hätte klarer machen sollen, dass ich das zum Nutzen des OP und zukünftiger Leser geschrieben habe, die möglicherweise nicht wissen, was ARC tut. Ich weiß genau, was Sie meinen, wollte nur nicht, dass jemand die falsche Schlussfolgerung zieht, dass das Mischen von ARC- und Nicht-ARC-Code ein Problem darstellt.
Caleb
16

Wie viel Nutzen kann ARC für ein Projekt bringen?

Der Vorteil ist ein erheblicher Schutz vor häufigen Fehlern bei der Speicherverwaltung. Leckagen, die dadurch verursacht werden, dass ein Objekt nicht freigegeben wird, und Abstürze, die darauf zurückzuführen sind, dass ein Objekt nicht beibehalten oder vorzeitig freigegeben wird, sollten erheblich verringert werden. Sie müssen das Referenzzählerspeichermodell noch verstehen, damit Sie Ihre Referenzen als stark oder schwach klassifizieren, Aufbewahrungszyklen vermeiden usw. können.

Wie viel kostet die Müllabfuhr wirklich?

In iOS gibt es keine Speicherbereinigung. ARC ähnelt GC darin, dass Sie Objekte nicht manuell beibehalten oder freigeben müssen. Es ist anders als bei GC, dass es keinen Müllsammler gibt. Das Retain / Release-Modell gilt weiterhin. Der Compiler fügt lediglich die entsprechenden Speicherverwaltungsaufrufe zur Kompilierungszeit für Sie in Ihren Code ein.

Haben Sie ARC verwendet und wenn ja, wie haben Sie es bisher gefunden?

Es ist ein wenig beunruhigend, wenn Sie es gewohnt sind, auf das Zählen zu verweisen, aber das ist nur eine Frage der Gewöhnung und des Vertrauens, dass der Compiler wirklich das Richtige tut. Es scheint eine Fortsetzung der Änderung der Eigenschaften zu sein, die mit Objective-C 2.0 einherging. Dies war ein weiterer großer Schritt zur Vereinfachung der Speicherverwaltung. Ohne die manuellen Speicherverwaltungsaufrufe wird Ihr Code etwas kürzer und leichter zu lesen.

Das einzige Problem mit ARC ist, dass es in älteren Versionen von iOS nicht unterstützt wird. Sie müssen dies berücksichtigen, bevor Sie sich für die Einführung entscheiden.

Caleb
quelle
1
Es gibt die bessere Antwort, über die ich gesprochen habe!
Jrturton
1
Ja, tolle Antwort. Gibt es also wirklich keinen Nachteil für ARC, außer lernen zu müssen, darauf zu vertrauen, dass es funktioniert? Es scheint zu schön, um in diesem Fall wahr zu sein?
Simon Withington
4

Ich denke, ARC ist eine großartige Idee. Im Vergleich zu GC können Sie Ihren Kuchen auch essen. Ich neige dazu zu glauben, dass MRC eine unschätzbare "Disziplin" für das Speichermanagement auferlegt, von der jeder profitieren würde. Ich stimme aber auch zu, dass das eigentliche Problem, dessen Sie sich bewusst sein müssen, Objektbesitz und Objektdiagramme sind (wie viele betont haben) und nicht die Referenzanzahl auf niedriger Ebene an sich.

Fazit: ARC ist KEINE Freikarte, um sich Gedanken über das Gedächtnis zu machen. Es ist ein Werkzeug, das Menschen dabei hilft, sich wiederholende Aufgaben zu vermeiden, die Stress verursachen und fehleranfällig sind und daher besser an eine Maschine (in diesem Fall den Compiler) delegiert werden.

Trotzdem bin ich persönlich eine Art Handwerker und habe den Übergang noch nicht geschafft. Ich habe gerade angefangen, Git zu benutzen ...

AKTUALISIEREN: Also habe ich mein gesamtes Spiel migriert, einschließlich der gl-Bibliothek, und bisher keine Probleme (außer mit dem Migrationsassistenten in Xcode 4.2). Wenn Sie ein neues Projekt starten, machen Sie es.

Nicolas Miari
quelle
2

Ich habe es in einigen (zugegebenermaßen kleinen) Projekten verwendet und habe nur gute Erfahrungen gemacht, sowohl was die Leistung als auch die Zuverlässigkeit betrifft.

Ein kleiner Hinweis zur Vorsicht ist, dass Sie die Do: s und Don't: s von schwachen Referenzen lernen müssen, um keine Referenzschleifen zu verursachen, wenn Sie Ihre Benutzeroberfläche selbst codieren. Der Designer leistet in der Regel gute Arbeit automatisch, wenn Sie Ihre GUI damit einrichten.

Joachim Isaksson
quelle
2

Der einzige Nachteil, auf den ich gestoßen bin, ist, wenn Sie eine Bibliothek mit vielen CoreFoundation-Funktionen und -Daten verwenden. In MRC mussten Sie sich keine Gedanken über die Verwendung von a CFStringRefanstelle von machen NSString*. In ARC müssen Sie angeben, wie die beiden interagieren (Basisbrücke? Geben Sie das CoreFoundation-Objekt frei und verschieben Sie es in ARC? Erstellen Sie ein Cocoa-Objekt als +1 CoreFoundation-Objekt?). Unter OS X ist es nur unter 64 verfügbar. Bitcode (obwohl ich einen Header habe, der das umgeht…).

MaddTheSane
quelle