61

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?

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Gauging
  • 705
  • 1
  • 6
  • 8
  • See also [why-java-and-python-garbage-collection-methods-are-different](http://stackoverflow.com/questions/21934/why-java-and-python-garbage-collection-methods-are-different) – nawfal Jul 20 '14 at 20:33

4 Answers4

73

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.

Community
  • 1
  • 1
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
  • 3
    Another advantage of ARC over libauto would be that is does not reduce the virtual address space. See http://stackoverflow.com/a/5522746/104790 – Nikolai Ruhe Feb 15 '12 at 14:48
  • 6
    I would stress that Chris Lattner is talking specifically about libauto and not about tracing garbage collection in general. I'd also point out that ARC is a form of garbage collection so it is non-sensical to talk about "ARC vs GC". You really mean "ARC vs tracing GC". – J D Jan 25 '14 at 15:24
  • 3
    @Asik - Perhaps my wording was imprecise. I've refined the above to indicate what I had meant, in that the retains and releases required for reference counting are what is inserted at compile time. Of course the reference counting itself occurs at runtime, but the point is that this avoids the collector process required for tracing garbage collection. The context of this question was about Objective-C (libauto) garbage collection, so I had assumed someone reading this would understand that "garbage collection" referred to tracing garbage collection, with a collector process. – Brad Larson Jan 30 '14 at 05:01
  • 2
    @Asik - As far as stutter goes, ARC is deterministic in where objects and object graphs are deallocated. That, combined with the fact that objects are deallocated as they are no longer needed, means that in practice you see far less stutter than from a collector process sweeping the object graph at particular intervals. Also, the fact that it is deterministic makes it easy to identify the points at which deallocation is causing a hitch or pause and to rework the appropriate operations to avoid or significantly reduce this. – Brad Larson Jan 30 '14 at 05:05
  • 1
    You're saying cycle collection is a "slight" advantage? Try to make more complicated use of blocks (ObjC closures) in your code. :-) Another difference is the CPU efficiency of tracing, which needn't litter your code with atomic refcount operations everywhere. – TaylanKammer Aug 11 '14 at 07:05
  • @BradLarson: "Of course the reference counting itself occurs at runtime, but the point is that this avoids the collector process required for tracing garbage collection". Incrementing and decrementing reference counts is more time consuming than tracing GC. This is why .NET and the JVM both use tracing GC. – J D Mar 03 '15 at 02:16
  • @BradLarson: "ARC is deterministic in where objects and object graphs are deallocated". Reference counting is non-deterministic in multithreaded programs because threads race to decrement to zero and the winner is responsible for cleanup. – J D Mar 03 '15 at 02:17
22

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.
Meseery
  • 1,845
  • 2
  • 22
  • 19
9

How does ARC differ from garbage collection?

ARC is a form of garbage collection.

You probably mean "what is the difference between ARC and tracing garbage collection (like the JVM and .NET)?". The main differences are that ARC is slower and leaks cycles. That's why the JVM and .NET both use tracing garbage collectors. For more information, please read How do reference counting and tracing garbage collection compare?.

J D
  • 48,105
  • 13
  • 171
  • 274
  • I know reference counting could leak cycles, but how it can be slower? As soon as RC reaches zero, resources can be released. No one can tell how long it takes before releasing resource in tracing GC, anything incorrect here? – http8086 Dec 12 '14 at 00:36
  • 1
    @hylepo: That is correct and often quoted but widly misleading. "As soon as RC reaches zero" but when does the count reach zero? Decrements are almost always deferred to the end of scope so objects are kept alive to the end of scope whether they are required or not. So, contrary to popular opinion, RC does not collect at the earliest point. "how it can be slower?". Reference counting is slow because it incurs a lot of counter increments and decrements that are usually non-local and, therefore, cache unfriendly. Even worse in a multithreaded context where inc/dec must be atomic. – J D Dec 12 '14 at 18:12
  • @hylepo: These are all solved problems but *all* of the solutions sacrifice the benefits you cited. For example, you can defer decrements in order to amortise costs but RC is then as unpredictable as tracing GC. Also note that RC is only predictable for single threaded programs. As soon as you have multithreading you can have decrements racing and you are unable to predict which thread will be stalled doing cleanup. – J D Dec 12 '14 at 18:15
-8

the short and sweet answer is as follow:

GC of java is Runtime, while ARC is compile time.

GC has reference to the objects at runtime and check for the dependencies of object runtime. While ARC appends the release, retain, autorelease calls at compiletime.

objectivecdeveloper
  • 1,050
  • 11
  • 29
  • 46
    -1 This is obviously not true. ARC bumps reference counts at run-time and releases only when they reach zero. Moreover, ARC is a form of garbage collection so you really mean "tracing garbage collection vs reference counted garbage collection". – J D Jan 25 '14 at 14:43
  • 27
    Wow, this is an example of how popular myths sustain themselves; it's insane that this gets voted up and accepted. As Jon Harrop said, this answer is simply wrong: reference counting is a *run-time* mechanism. – Asik Jan 30 '14 at 03:31
  • 4
    As others have noted, this answer is plain wrong. GC might be one of the topics with the most frivolous myths and misconceptions out there. Doesn't help having some pseudointellectual people spread well cooked lies around either. http://taylanub.github.io/webapps-js-gc/ – TaylanKammer Aug 11 '14 at 07:10
  • 9
    This answer is correct: the release and retain calls *are* added at compile time. Yes, the actual increment/decrement happens at runtime, obviously, but the calls are inserted at runtime. – Jimothy Oct 24 '14 at 01:06
  • 11
    Automatic Reference Counting (ARC) is a compile time feature. Specifically, ARC automatically injects Obective-C runtime equivalents for retain, release and autorelease at compile time using LLVM. Without ARC or GC, you would need to manually add calls to retain and release, which would be Manual Reference Counting (MRC). In the case of the latter, human beings add the calls in the source code at development time, not at runtime or compile time. The strategy for how those calls are added should not be confused with the strategy of reference counting itself, which does occur at runtime. – Scott Ahten Oct 10 '15 at 23:50
  • 1
    ARC is different in that it injects optimized Objective-C runtime equivalents for retain, release and autorelease. For example, objc_release() is added, rather than [NSObject release]. ARC can even optimize out calls to all together. This gives a slight performance improvement over manually adding calls to retain, release and autorelease. See: https://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html – Scott Ahten Oct 11 '15 at 00:04
  • 1
    This is not true – Jakub Truhlář Jun 21 '17 at 08:08