To ARC or not to ARC? What are the pros and cons?

23,326

Solution 1

There is no downside. Use it. Do it today. It is faster than your old code. It is safer than your old code. It is easier than your old code. It is not garbage collection. It has no GC runtime overhead. The compiler inserts retains and releases in all the places you should have anyway. But it's smarter than you and can optimize out the ones that aren't actually needed (just like it can unroll loops, eliminate temporary variables, inline functions, etc.)

OK, now I will tell you about the small downsides:

  • If you're a long-time ObjC developer, you will twitch for about a week when you see ARC code. You will very quickly get over this.

  • There are some (very) small complications in bridging to Core Foundation code. There are slightly more complications in dealing with anything that treats an id as a void*. Things like C-arrays of id can take a little more thinking about to do correctly. Fancy handling of ObjC va_args can also cause trouble. Most things involving math on an ObjC pointer is trickier. You shouldn't have much of this in any case.

  • You cannot put an id in a struct. This is fairly rare, but sometimes it's used to pack data.

  • If you did not follow correct KVC naming, and you intermix ARC and non-ARC code, you will have memory problems. ARC uses KVC naming to make decisions about memory management. If it's all ARC code, then it doesn't matter because it will do it the same "wrong" on both sides. But if it's mixed ARC/non-ARC then there's a mismatch.

  • ARC will leak memory during ObjC exception throws. An ObjC exception should be very close in time to the termination of your program. If you're catching a significant number of ObjC exceptions, you're using them incorrectly. This is fixable using -fobjc-arc-exceptions, but it incurs the penalties discussed below:

  • ARC will not leak memory during ObjC or C++ exception throws in ObjC++ code, but this is at the cost of both time and space performance. This is yet another in a long list of reasons to minimize your use of ObjC++.

  • ARC will not work at all on iPhoneOS 3 or Mac OS X 10.5 or earlier. (This precludes me from using ARC in many projects.)

  • __weak pointers do not work correctly on iOS 4 or Mac OS X 10.6, which is a shame, but fairly easy to work around. __weak pointers are great, but they're not the #1 selling point of ARC.

For 95%+ of code out there, ARC is brilliant and there is no reason at all to avoid it (provided you can handle the OS version restrictions). For non-ARC code, you can pass -fno-objc-arc on a file-by-file basis. Xcode unfortunately makes this much harder than it should be to do in practice. You should probably move non-ARC code into a separate xcodeproj to simplify this.

In conclusion, switch to ARC as soon as you can and never look back.


EDIT

I've seen a couple of comments along the lines of "using ARC is no substitute for knowing the Cocoa memory management rules." This is mostly true, but it's important to understand why and why not. First, if all of your code uses ARC, and you violate the Three Magic Words all over the place, you'll still have no problems. Shocking to say, but there you go. ARC might retain some things that you didn't mean it to retain, but it'll release them as well, so it'll never matter. If I were teaching a new class in Cocoa today, I'd probably spend no more than five minutes on the actual memory management rules, and I'd probably only mention the memory management naming rules while discussing KVC naming. With ARC, I believe you could actually become a decent beginning programmer without learning the memory management rules at all.

But you couldn't become a decent intermediate programmer. You need to know the rules in order to bridge correctly with Core Foundation, and every intermediate programmer needs to deal with CF at some point. And you need to know the rules for mixed-ARC/MRC code. And you need to know the rules when you start messing around with void* pointers to id (which you continue to need to perform KVO correctly). And blocks... well, block memory management is just weird.

So my point is that the underlying memory management is still important, but where I used to spend significant time stating and restating the rules for new programmers, with ARC it is becoming a more advanced topic. I'd rather get new developers thinking in terms of object graphs rather than fill their heads with the underlying calls to objc_retain().

Solution 2

Better, more technical answers than mine will come, but here goes:

  • ARC != garbage collection. There is no run time penalty, it is done at compile time.
  • ARC also != just auto releasing everything, as you suggest in your comment. Read the docs
  • It's awesome once you realise how much manual reference management you were doing
  • Use it!
  • One drawback - maintaining old, non-arc code suddenly becomes very tedious.

Solution 3

How much benefit can ARC bring to a project?

The benefit is a significant degree of protection from common memory management mistakes. Leaks caused by failing to release an object and crashes due to failing to retain or prematurely releasing an object should be significantly decreased. You still need to understand the reference counted memory model so that you can classify your references as strong or weak, avoid retain cycles, and so on.

How much does garbage collection really 'cost'?

There is no garbage collection in iOS. ARC is similar to GC in that you don't have to manually retain or release objects. It's unlike GC in that there's no garbage collector. The retain/release model still applies, it's just that the compiler inserts the appropriate memory management calls into your code for you at compile time.

Have you been using ARC and if so, how have you found it so far?

It's a little disconcerting if you're used to reference counting, but that's just a matter of getting used to it and learning to trust that the compiler really will do the right thing. It feels like a continuation of the change to properties that came with Objective-C 2.0, which was another big step toward simplifying memory management. Without the manual memory management calls, your code becomes a little shorter and easier to read.

The only issue with ARC is that it's not supported in older versions of iOS, so you need to take that into account before you decide to adopt it.

Solution 4

I think ARC is a great idea. Compared to GC, you can have your cake and eat it too. I tend to believe that MRC imposes an invaluable 'discipline' towards memory management that everyone would benefit from having. But I also agree that the real issue to be aware of is Object Ownership and Object Graphs (as many have pointed out), and not low-level reference counts per se.

To conclude: ARC is NOT a free pass to be mindless about memory; it is a tool to help humans avoid repetitive tasks, that cause stress and are prone to error, therefore better delegated to a machine (the compiler, in this case).

That said, I'm personally kind of a craftsman and haven't made the transition yet. I just started using Git...

UPDATE: So I migrated my whole game, gl library included, and no problems so far (except with the migration assistant in Xcode 4.2). If you are starting a new project, go for it.

Solution 5

The only downside I have encountered is if you use a library with a lot of CoreFoundation functions and data. In MRC you didn't need to worry about using a CFStringRef instead of an NSString*. In ARC, you have to specify how the two interact (basic bridge? release the CoreFoundation object and move it to ARC? Make a Cocoa object as a +1 CoreFoundation retained object?) Also, on OS X, it's only available on 64-bit code (Although I do have a header that works around that…).

Share:
23,326

Related videos on Youtube

Simon Withington
Author by

Simon Withington

iOS Developer based in Newcastle-upon-Tyne, UK. ShinobiControls Ninja and bedroom app developer.

Updated on July 26, 2022

Comments

  • Simon Withington
    Simon Withington almost 2 years

    I've yet to use ARC, since the majority of the code in the project I'm working on at the moment was written pre-iOS 5.0.

    I was just wondering, does the convenience of not retaining/releasing manually (and presumably more reliable code that comes as a result?) outweigh any 'cost' of using ARC? What are your experiences of ARC, and would you recommend it?

    So:

    • How much benefit can ARC bring to a project?
    • Does ARC have a cost like garbage collection in Java?
    • Have you been using ARC and if so, how have you found it so far?
    • Sergey Kalinichenko
      Sergey Kalinichenko over 12 years
      There is no garbage collection on ipad/ios. Are you talking about OS X?
    • Simon Withington
      Simon Withington over 12 years
      My apologies, I'm using Java terms out-of-place. I mean that with ARC, objects can be kept in memory for longer than necessary, then released as a group in an auto-release pool some time later. It is this effect of them being kept and released with other objects later, similarly to Java's garbage collection that I am referring to.
    • Rob Napier
      Rob Napier over 12 years
      @TenementFunster, for the same code (minus the calls to release), ARC will hold the object around no longer than non-ARC code. In fact, it often will release it sooner than you would have. There are a small number of things that are somewhat slower, but they sped up the common patterns so much that it dwarfs the performance impact. For many common patterns (retaining an object that was returned with an autorelease for instance), you literally can't write it by hand as fast as ARC will do it automatically.
    • Brad Larson
      Brad Larson over 12 years
      In regards to garbage collection, see my answer to this similar question: What is the difference between Objective-C automatic reference counting and garbage collection?
  • jrturton
    jrturton over 12 years
    There's the better answer I was talking about!
  • Simon Withington
    Simon Withington over 12 years
    Yeah, that's why I've not used it so far - I'm not sure I could bear to go through our substantial amount of pre-existing code to convert it... I'll definitely try it out next project though. Thanks for your answer :)
  • Simon Withington
    Simon Withington over 12 years
    Yeah, great answer. So is there really no drawback to ARC aside from having to learn to trust that it works? It seems too good to be true in that case?
  • Caleb
    Caleb over 12 years
    It's not that maintaining old code becomes any more difficult, it's that your expectation has changed. So it's not really fair to blame ARC for making life easier. Xcode makes it easy to convert your old code to ARC when you're ready, but you obviously can't use it if you still need to support older iOS versions.
  • jrturton
    jrturton over 12 years
    @Caleb I wasn't blaming ARC, it's just that's the only downside I've seen so far - its spoiled me rotten in the space of a single project.
  • Simon Withington
    Simon Withington over 12 years
    Thanks for taking the time to type all that out Rob - after reading everything people have written here I think the biggest hurdle will be my initial mistrust of letting the compiler worry about it, and possibly sore hands after slapping myself everytime I start typing ret-(tab) or rel-(tab)!
  • Rob Napier
    Rob Napier over 12 years
    Yeah; I didn't list that as a problem, but there is a small issue of getting out of memory management practice when you have to switch between code-bases. Some of my projects run on 10.4, so I still do a lot of Objective-C 1.0 work (so no @synthesize, let alone ARC). But you get used to switching modes pretty well.
  • Caleb
    Caleb over 12 years
    @jrturton I should have made it more clear that I wrote that for the benefit of the OP and future readers who may not grok what ARC does. I know exactly what you mean, just didn't want anyone to draw the mistaken conclusion that mixing ARC and non-ARC code creates a problem.
  • Catfish_Man
    Catfish_Man over 12 years
    One thing to be very careful of (in non-ARC as well, but moreso in ARC because it's so invisible now) is retain cycles. My advice here is 1) if you find yourself storing an objc block as an instance variable, take a long hard look at it to see if it could capture the object it's an ivar of, even indirectly. 2) Actually design your object graph, rather than just letting it happen. You must know what owns what if you want to write good code. 3) Use heapshots: friday.com/bbum/2010/10/17/…
  • Rob Napier
    Rob Napier over 12 years
    @Catfish_Man All good points. Retain loops have always been a problem. Apple's new advice is exactly as you say in #2. We need to think about object graphs rather than retain and release. #1 is a serious problem with blocks, and one of several reasons I find blocks a mixed blessing that should be approached with caution.
  • Abizern
    Abizern over 12 years
    @RobNapier Please, please add a caveat that using ARC is not an alternative to learning about memory management.
  • Rob Napier
    Rob Napier over 12 years
    @Abizern, updated the answer with my thoughts on the subject.
  • Abizern
    Abizern over 12 years
    @RobNapier And I agree. Thanks. Thinking about objects as part of a graph is a much better way of visualising lifetimes.
  • Rabbit
    Rabbit over 12 years
    There is one serious downside that wasn't mentioned: cross-compatibility. For us brave and foolish souls that face the wastelands known as cross-platform programming, ARC simply isn't an option, at least not until GNU expand upon their ObjC runtime and compiler features again (they say more is on the way).
  • ZhangChn
    ZhangChn over 12 years
    You can use ARC except that you need to support iOS 3.x devices. BTW, make sure to use of Xcode to do the transition (Edit > Refactor > Convert to Objective-C ARC). During the process Xcode would do a lot of validation to make sure your code would work and figure out any codes that violates those designing guidelines.
  • Juan Munhoes Junior
    Juan Munhoes Junior over 11 years
    brilliant answer @RobNapier.
  • Ajay Sharma
    Ajay Sharma almost 11 years
    Excellent .. answer with pointwise. that's 100th from me. Congrates for a century ;)
  • pronebird
    pronebird over 10 years
    I can't believe somebody seriously talks about iOS 3.x in 2012.