Most of Apples documentation seems to avoid using autoreleased objects especially when creating gui views, but I want to know what the cost of using autoreleased objects is?
Old thread, but chipping on for the benefit of newer readers.
I use autorelease vs retain/release depending on the risk of autorelease bugs specific to an object and the size of the object. If I'm just adding some tiny UIImageViews, or a couple of UILabels to my view, autorelease keeps the code readable and manageable. And when the view is removed and dealloced, these subviews should get released soon enough.
If on the other hand we're talking about a UIWebView (high risk of autorelease bugs), or of course some data that needs to be persistent till the 'death' of the object, retain/release is the way to go.
Honestly, my projects have not gotten that big yet, where the additional 'staying-time' of autoreleased objects would create a memory problem. For complex apps, that concern is legitimate.
In any case, I don't think a one-size-fits-all approach would be right. You use whatever approach - or combination of approaches - is right for the project, keeping all the factors mentioned above in mind.
There are two costs:
(Assuming you have an option to avoid autoreleased objects.) You effectively unnecessarily extend the lifetime of your objects. This can mean that your memory footprint grows -- unnecessarily. On a constrained platform, this can mean that your application is terminated if it exceeds a limit. Even if you don't exceed a limit, it may cause your system to start swapping, which is very inefficient.
The additional overhead of finding the current autorelease pool, adding the autoreleased object to it, and then releasing the object at the end (an extra method call). This may not be a large overhead, but it can add up.
Best practice on any platform is to try to avoid autorelease if you can.
To answer the questions:
Ultimately should I use a strategy where everything is autoreleased and using retain/release should be the exception to the rule for specific cases?
Quite the opposite.
Or should I generally be using retain/release with autorelease being the exception for returned objects from convenience methods like [NSString stringWithEtc...] ?
You should always use retain/release if you can -- in the case of NSString
there is typically no need to use stringWithEtc
methods as there are initWithEtc
equivalents.
See also this question.
I notice the code sample you provided is for the iPhone. Apple specifically recommends avoiding autoreleased objects for iPhone apps. I can't find the specific reasoning, but they were hammering this point at WWDC.
I generally use autoreleased objects these days because they tend to result in simpler, easier to read code. You declare and initialize them, then let the drop out of scope. Mechanically they exist quite a bit longer, but from the perspective of the person writing the code it is equivalent to a stack declared object in C++ automatically being destructed when the function returns and its frame is destroyed.
While there is an efficiency loss, in most cases it is not significant. The bigger issue is the more extant objects and later memory recovery can lead to a more fragmented address space. If that is an issue it usually is fairly simple to go in and switch to manual retain/release in a few hot methods and improve it.
As others have said, readability trumps performance in nonperformance sensitive code. There are a number of cases where using autoreleased objects leads to more memory fragmentation, but in any case where the object will outlive the pool it will not. In those cases the only price you are paying is finding the cost of finding the correct autorelease pool.
I'm surprised nobody has mentioned this yet. The biggest reason to avoid autoreleased objects when you can has nothing to do with performance. Yes, all of the performance concerns mentioned here are absolutely valid, but the biggest downside to autorelease is that it makes debugging significantly more difficult.
If you have an overreleased object that's never autoreleased, it's trivially easy to track down. If you have a user-reported crash that happens intermittently with a backtrace somewhere south of NSPopAutoreleasePool, good luck...
The costs are:
If you want to be very conservative with your memory usage, you should avoid autorelease. However, it is a useful technique that can make code more readable. Obsessively using retain/release falls under the umbrella of "premature optimization."
If you are in Cocoa's main event handling thread (which you are most of the time), the autorelease pool is emptied when control returns to the event handler. If your method is short and doesn't loop over large amounts of data, using autorelease to defer deallocation to the end of the run loop is fine.
The time to be wary of autorelease is when you are in a loop. For example, you are iterating over a user's address book and perhaps loading an image file for each entry. If all of those image objects are autoreleased, they will accumulate in memory until you have visited the entire address book. If the address book is large enough, you may run out of memory. If you release the images as soon as you are done with them, within the loop, your app can recycle the memory.
If you can't avoid autoreleasing inside a loop (it's being done by code you didn't write and can't change), you can also manage an NSAutoreleasePool within the loop yourself if needed.
So, be mindful of using autorelease inside loops (or methods that may be called from loops), but don't avoid it when it can make code more readable.