ARC spielt nur das alte Retain / Release (MRC) ab, wobei der Compiler herausfindet, wann Retain / Release aufgerufen werden soll. Es weist tendenziell eine höhere Leistung, eine geringere Spitzenauslastung des Speichers und eine besser vorhersehbare Leistung als ein GC-System auf.
Andererseits sind einige Arten von Datenstrukturen mit ARC (oder MRC) nicht möglich, während GC sie verarbeiten kann.
Wenn Sie beispielsweise eine Klasse mit dem Namen node haben und node ein NSArray mit untergeordneten Elementen und einen einzelnen Verweis auf das übergeordnete Element hat, der mit GC "nur funktioniert". Mit ARC (und auch der manuellen Referenzzählung) haben Sie ein Problem. Jeder gegebene Knoten wird von seinen untergeordneten und auch von seinen übergeordneten Knoten referenziert.
Mögen:
A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A
Alles ist in Ordnung, während Sie A verwenden (z. B. über eine lokale Variable).
Wenn Sie damit fertig sind (und B1 / B2 / B3), wird ein GC-System schließlich entscheiden, alles zu betrachten, was es finden kann, beginnend mit den Stapel- und CPU-Registern. Es wird niemals A, B1, B2, B3 finden, also werden sie finalisiert und der Speicher in andere Objekte zurückgeführt.
Wenn Sie ARC oder MRC verwenden und mit A abschließen, hat es eine Nachzählung von 3 (B1, B2 und B3 beziehen sich alle darauf), und B1 / B2 / B3 haben alle eine Referenzanzahl von 1 (A's NSArray enthält eine Referenz auf jeder). Alle diese Objekte bleiben also lebendig, obwohl nichts sie jemals verwenden kann.
Die übliche Lösung besteht darin, zu entscheiden, dass eine dieser Referenzen schwach sein muss (nicht zur Referenzanzahl beitragen). Dies funktioniert für einige Verwendungsmuster, z. B. 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 wieder nach oben zu klettern und A zu finden. Mit einer schwachen Referenz, wenn Sie nur an B1 festhalten, kann (und wird) A verdampfen und B2 und B3 nehmen damit.
Manchmal ist dies kein Problem, aber einige sehr nützliche und natürliche Methoden zum Arbeiten mit komplexen Datenstrukturen sind mit ARC / MRC sehr schwierig zu verwenden.
ARC zielt also auf die gleichen Probleme ab, auf die GC abzielt. 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 verlassenem Speicher und kann schwerwiegende Auslagerungsprobleme verursachen oder nicht genügend Speicher oder Auslagerungsspeicher haben).
Sie können auch sagen, dass ARC der Leistung (oder vielleicht der Vorhersagbarkeit) eine höhere Priorität einräumt, während GC der generischen Lösung eine höhere Priorität einräumt. Infolgedessen hat GC weniger vorhersehbare CPU- / Speicheranforderungen und (normalerweise) eine geringere Leistung als ARC, kann jedoch jedes Nutzungsmuster verarbeiten. ARC funktioniert viel besser für viele, viele gängige Nutzungsmuster, aber für einige (gültige!) Nutzungsmuster fällt es um und stirbt ab.