What is the difference between Objective-C automatic reference counting and garbage collection?

With the new automatic reference counting (ARC) introduced in Xcode 4.2, we no longer need to manually manage retain / release in Objective-C.

This seems similar to garbage collection, as done in Objective-C on the Mac, and in other languages. How does ARC differ from garbage collection?


As I describe in my answer here, ARC can provide the best of both manual memory management and tracing garbage collection. It mostly removes the need for a developer to track manual retains, releases, and autoreleases on Objective-C objects, yet avoids the need for a garbage collector process which can use up limited resources on a mobile device and cause occasional stutters in a running application.

ARC inserts the appropriate retains and releases required for reference counting at compile time, by applying the rules that all Objective-C developers have had to use over the years. This frees the developer from having to manage this themselves. Because the retains and release are inserted at compile time, no collector process is needed to continually sweep memory and remove unreferenced objects.

One slight advantage that tracing garbage collection has over ARC is that ARC will not deal with retain cycles for you, where tracing garbage collection can pick these up.

A great read on the subject comes from this thread on Apple's Objective-C mailing list, where Chris Lattner has this to say:

The primary advantage of GC over ARC is that it collects retain cycles. A secondary advantage is that "retained" assignments are "atomic" because they are a simple store. ARC has several big advantages over libauto GC:

  1. It has deterministic reclamation of objects (when the last strong reference to the object goes away) where GC frees an object "sometime later". This defines away a class of subtle bugs that can exist in GC apps that aren't exposed because the collector doesn't trigger "in the buggy window".
  2. The high water mark is generally much lower with ARC than GC because objects are released sooner.
  3. libauto provides a fragile programming model, you have to be careful to not lose write barriers etc.
  4. not all of the system frameworks are GC clean, and the frameworks do occasionally regress as they evolve.
  5. ARC doesn't suffer from false roots. libauto conservatively scans the stack, which means that integers that look like pointers can root object graphs.
  6. ARC doesn't have anything that kicks in and stops your app, causing UI stutters. libauto is pretty advanced as far as GC implementations go because it doesn't immediately stop every thread, but it still does usually end up stopping all the UI threads.

I am currently migrating both my manually memory managed projects, as well as those using Objective-C garbage collection, to ARC. After using garbage collection in a couple of Mac applications for a while now, I see some significant advantages in moving these projects to ARC.


ARC rely on a compile time "referenced" objects which make it efficient in a low-power mode environments (Mobile devices).

GC rely on a runtime based "reachable" objects which make it efficient in a multi-threaded environment.

Operation

ARC injects a code into the executable to be executed "automatically" on unused objects depending on their reference count.

GC works in the runtime as it will detect the unused object graphs (will eliminate retain-cycles) and remove them on an indeterminate time intervals

Advantages of Automatic Reference Counting

  • Real-time, deterministic destruction of objects as they become unused.
  • No background processing.

Advantages of Garbage Collection

  • GC can clean up entire object graphs, including retain cycles.
  • GC proceed in the background, so less memory management work is done as part of the regular application flow.

Disadvantages of Automatic Reference Counting

  • ARC cannot handle retain cycles automatically.

Disadvantages of Garbage Collection

  • Because GC happens in the background, the exact time frame for object releases is undetermined.
  • When a GC happens, other threads in the application may be temporarily put on hold.