webentwicklung-frage-antwort-db.com.de

Wie funktioniert der neue automatische Referenzzählmechanismus?

Kann mir jemand kurz erklären, wie ARC funktioniert? Ich weiß, es unterscheidet sich von Garbage Collection, aber ich habe mich nur gefragt, wie es genau funktioniert.

Wenn ARC das tut, was GC tut, ohne die Leistung zu beeinträchtigen, warum verwendet Java dann GC? Warum verwendet es nicht auch ARC?

201
user635064

Jeder neue Entwickler, der zu Objective-C kommt, muss die strengen Regeln lernen, wann Objekte beibehalten, freigegeben und freigegeben werden müssen. Diese Regeln geben sogar Namenskonventionen an, die die Anzahl der von Methoden zurückgegebenen Objekte einschließen. Die Speicherverwaltung in Objective-C wird zur zweiten Natur, wenn Sie sich diese Regeln zu Herzen nehmen und sie konsequent anwenden, aber selbst die erfahrensten Cocoa-Entwickler geraten von Zeit zu Zeit ins Wanken.

Mit dem Clang Static Analyzer erkannten die LLVM-Entwickler, dass diese Regeln zuverlässig genug waren, um ein Tool zu entwickeln, mit dem auf Speicherlecks und Überlappungen in den Pfaden hingewiesen werden kann, die in Ihrem Code verwendet werden.

Automatische Referenzzählung (ARC) ist der nächste logische Schritt. Wenn der Compiler erkennen kann, wo Sie Objekte aufbewahren und freigeben sollten, warum sollte er nicht den Code für Sie einfügen? Die starren, sich wiederholenden Aufgaben sind das, was die Compiler und ihre Brüder großartig sind. Menschen vergessen Dinge und machen Fehler, aber Computer sind viel einheitlicher.

Dies befreit Sie jedoch nicht vollständig von der Speicherverwaltung auf diesen Plattformen. Ich beschreibe das Hauptproblem, auf das Sie achten sollten (Zyklen einhalten) in meiner Antwort hier . Dies erfordert möglicherweise ein wenig Nachdenken Ihrer Seite, um schwache Zeiger zu kennzeichnen. Dies ist jedoch im Vergleich zu dem, was Sie in ARC erzielen, gering.

Verglichen mit der manuellen Speicherverwaltung und der Speicherbereinigung bietet ARC Ihnen das Beste aus beiden Welten, indem Sie die Notwendigkeit des Schreibens von Speicher-/Freigabecode weglassen, ohne dass die Speicher- und Sägezahn-Speicherprofile in einer Speicherbereinigungsumgebung angezeigt werden. Die einzigen Vorteile der Müllsammlung sind die Möglichkeit, Aufbewahrungszyklen zu bewältigen, und die Tatsache, dass atomare Eigenschaftszuweisungen kostengünstig sind (wie hier ). Ich weiß, dass ich meinen gesamten Mac GC-Code durch ARC-Implementierungen ersetzen werde.

Ob dies auf andere Sprachen ausgedehnt werden kann, scheint auf das Referenzzählsystem in Objective-C ausgerichtet zu sein. Es kann schwierig sein, dies auf Java oder andere Sprachen anzuwenden, aber ich weiß nicht genug über die Low-Level-Compiler-Details, um dort eine endgültige Aussage zu treffen. Angesichts der Tatsache, dass Apple diese Bemühungen in der LLVM vorantreibt, wird Objective-C an erster Stelle stehen, es sei denn, eine andere Partei stellt erhebliche Ressourcen in diese Richtung.

Die Enthüllung dieses Entwicklers bei der WWDC schockierte, so dass die Leute nicht wussten, dass so etwas getan werden könnte. Es kann im Laufe der Zeit auf anderen Plattformen erscheinen, ist aber für LLVM und Objective-C derzeit exklusiv.

241
Brad Larson

Bei ARC handelt es sich einfach um alte Retain/Release (MRC), wobei der Compiler herausfindet, wann er Retain/Release aufrufen soll. Es wird tendenziell eine höhere Leistung, eine geringere Spitzenauslastung des Speichers und eine besser vorhersagbare Leistung aufweisen als bei einem GC-System.

Andererseits sind einige Arten von Datenstrukturen mit ARC (oder MRC) nicht möglich, während GC sie verarbeiten kann.

Beispiel: Wenn Sie über eine Klasse mit dem Namen node verfügen und der Knoten über ein NSArray mit untergeordneten Elementen verfügt, sowie einen einzelnen Verweis auf das übergeordnete übergeordnete Element, das mit GC "funktioniert". Mit ARC (und auch manuellem Referenzzählen) haben Sie ein Problem. Auf einen gegebenen Knoten wird von seinen untergeordneten und auch von seinem übergeordneten Knoten verwiesen.

Mögen:

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

Alles ist in Ordnung, wenn Sie A verwenden (zB über eine lokale Variable).

Wenn Sie damit fertig sind (und B1/B2/B3), entscheidet sich ein GC-System schließlich für alles, was es von den Stack- und CPU-Registern aus finden kann. A, B1, B2, B3 wird nie gefunden, so dass sie finalisiert werden und der Speicher in andere Objekte verwandelt wird.

Wenn Sie ARC oder MRC verwenden und mit A abschließen, hat es eine Nachzählung von 3 (B1, B2 und B3 verweisen darauf), und B1/B2/B3 hat alle eine Referenzzählung von 1 (A's NSArray enthält eine Referenz.) jeder). Alle diese Objekte bleiben also lebendig, auch wenn sie niemals verwendet werden können.

Die übliche Lösung besteht darin, zu entscheiden, dass eine dieser Referenzen schwach sein muss (nicht zur Referenzzählung beitragen). Dies funktioniert für einige Verwendungsmuster, zum Beispiel, wenn Sie B1/B2/B3 nur über A referenzieren. In anderen Mustern schlägt dies jedoch fehl. Zum Beispiel, wenn Sie manchmal an B1 festhalten und erwarten, über den übergeordneten Zeiger nach oben zu klettern und nach A zu suchen. Wenn Sie nur an B1 festhalten, kann A (und normalerweise) verdunsten und B2 und B3 nehmen damit.

Manchmal ist dies kein Problem, aber einige sehr nützliche und natürliche Methoden, mit komplexen Datenstrukturen zu arbeiten, sind mit ARC/MRC sehr schwierig zu verwenden.

ARC zielt also auf die gleiche Art von GC-Zielen ab. ARC arbeitet jedoch mit einer begrenzten Anzahl von Verwendungsmustern als GC. Wenn Sie also eine GC-Sprache (wie Java) verwenden und etwas wie ARC darauf pfropfen, funktionieren einige Programme nicht mehr (oder generieren zumindest Tonnen von aufgegebenem Speicher.) und kann zu schwerwiegenden Auslagerungsproblemen führen oder der Speicher oder der Auslagerungsspeicher sind knapp).

Man kann auch sagen, dass ARC der Performance (oder der Vorhersagbarkeit) eine höhere Priorität einräumt, während GC der Generikallösung Priorität einräumt. Infolgedessen hat GC weniger vorhersagbare CPU-/Speicheranforderungen und eine (normalerweise) geringere Leistung als ARC, kann jedoch jedes Verwendungsmuster verarbeiten. ARC wird für viele häufig verwendete Verwendungsmuster viel besser funktionieren, aber für ein paar (gültige!) Verwendungsmuster wird es umkippen und sterben.

22
Stripes

Zauber

Genauer gesagt funktioniert ARC genau so, wie Sie es mit Ihrem Code tun würden (mit einigen geringfügigen Unterschieden). ARC ist eine Compile-Time-Technologie, im Gegensatz zu GC, die zur Laufzeit läuft und die Leistung negativ beeinflusst. ARC verfolgt für Sie die Referenzen auf Objekte und synthetisiert die Retain/Release/Autorelease-Methoden gemäß den normalen Regeln. Aus diesem Grund kann ARC auch Dinge freigeben, sobald sie nicht mehr benötigt werden, anstatt sie aus rein konventionellen Gründen in einen Autorelease-Pool zu werfen.

Einige andere Verbesserungen umfassen das Nullen von schwachen Referenzen, das automatische Kopieren von Blöcken auf den Heap sowie Beschleunigungen auf der ganzen Linie (6x für Autorelease-Pools).

Eine ausführlichere Diskussion darüber, wie all dies funktioniert, finden Sie im LLVM Docs on ARC.

4
Joshua Weinberg

Es variiert stark von der Müllsammlung. Haben Sie die Warnungen gesehen, die Sie darauf hinweisen, dass möglicherweise Gegenstände auf verschiedenen Leitungen auslaufen? Diese Anweisungen sagen Ihnen sogar, in welcher Zeile Sie das Objekt zugewiesen haben. Dies ist einen Schritt weiter gegangen und kann jetzt retain/release-Anweisungen an den richtigen Stellen einfügen, besser als bei den meisten Programmierern, fast zu 100%. Gelegentlich gibt es einige seltsame Instanzen von zurückgehaltenen Objekten, mit denen Sie helfen müssen.

3
FreeAsInBeer

ARC ist eine Compilerfunktion, die die automatische Speicherverwaltung von Objekten ermöglicht.

Anstatt sich zu merken, wann retain, release und autorelease zu verwenden sind, wertet ARC die Lebensdauerbedingungen Ihrer Objekte aus und fügt beim Kompilieren automatisch entsprechende Speicherverwaltungsaufrufe für Sie ein. Der Compiler generiert auch entsprechende Dealloc-Methoden für Sie.

Der Compiler fügt die erforderlichen retain/release-Aufrufe zur Kompilierungszeit ein, aber diese Aufrufe werden wie jeder andere Code zur Laufzeit ausgeführt.

Das folgende Diagramm soll Ihnen ein besseres Verständnis der Funktionsweise von ARC vermitteln.

enter image description here

Diejenigen, die neu in der iOS-Entwicklung sind und keine Erfahrung mit Objective C haben. Weitere Informationen zur Speicherverwaltung finden Sie in der Apple-Dokumentation zu Advanced Memory Management Programming Guide .

0
Yogesh Bharate

Sehr gut erklärt durch Apple-Entwicklerdokumentation. Lesen Sie "Wie ARC funktioniert"

Um sicherzustellen, dass Instanzen nicht verschwinden, solange sie noch benötigt werden, verfolgt ARC, wie viele Eigenschaften, Konstanten und Variablen derzeit auf jede Klasseninstanz verweisen. ARC hebt eine Instanz nicht auf, solange noch mindestens eine aktive Referenz auf diese Instanz vorhanden ist.

Um sicherzustellen, dass Instanzen nicht verschwinden, solange sie noch benötigt werden, verfolgt ARC, wie viele Eigenschaften, Konstanten und Variablen derzeit auf jede Klasseninstanz verweisen. ARC hebt eine Instanz nicht auf, solange noch mindestens eine aktive Referenz auf diese Instanz vorhanden ist.

Wissen Diff. zwischen Garbage Collection und ARC: Lesen Dies

0
Lalit Kumar