I've been told to not worry about retain counts. I understand that I shouldn't decide to release or retain using conditional logic based on retainCount, but should I not worry about it? I thought these correspond to memory usage in some way.
For instance, if I have a bunch of subviews of UIView that I've also put into an NSArray to be able to iterate through them, doesn't that double the retain count and therefore the memory use of the application? If so, is this costly or trivial, if the subviews are, say, 500 UIControl instances? This is assuming that I need the 500 instances, of course.
The value returned by retainCount is the absolute number of times the object has been retained. A UIView comes from a framework whose implementation is opaque. The implementation details aren't something you should worry about save for the documented interface you interact with.
And within that implementation, instances of UIView may be retained any number of times as a part of the implementation. In terms of memory, the actual number of retains is meaningless; 1 is the same as 5.
The only thing you should ever be concerned with is how your code changes an objects retain count.
If your code increases the retain count, it must decrease it somewhere or the object will stick around forever. If you retain, you must release (or autorelease). If you copy, you must release or autorelease. If you new or alloc, you must release (or autorelease).
That is it.
You're not supposed to be worrying about retainCount because it's often a misleading implementation detail of the reference counting system. What you're supposed to concern yourself with is following proper object ownership policy.
I post this once in a while from Apple's documentation:
Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.
As for your last question, your memory usage is not going to double from adding objects from one array to another array. The retain count is just an unsigned integer in the object that gets incremented by 1 when something claims ownership of it. But again, don't concern yourself with that.
For instance, if I have a bunch of subviews of UIView that I've also put into an NSArray to be able to iterate through them, doesn't that double the retain count...
Yes, it will.
... and therefore the memory use of the application?
No! The conclusion is wrong. 1000000 takes as much space as 0 when stored as a 32-bit integer.
The reason they say not to worry is that the retainCount field can often be very misleading. Aside from not knowing when the autorelease pool was last flushed or how many times an object has been autoreleased since, there are also some complicated internals, and system components could be temporarily holding references in ways that cannot be predicted. So if you start to study the retainCount you'll likely spend a lot time trying to figure out what other parts of the system are doing with various objects, which is not likely to help you get your application right.
You should design how your application works so that memory usage is not excessive.
You should worry about how many objects you have in memory, and how many times you have retained them (this is a number that will be less than the retainCount), and making sure you release them as many times as you retain them.
Calling retain on an object multiple times still only results in a single copy of the object being in memory.
To check for memory usage and/or leaks, you use the instruments leaks detector.
The retain count is just a number. An object whose retain count hits zero will get deallocated; aside from that, it doesn't matter if it's been retained once or fifty times.
Related
For instance:
we always write like this way 1:
-(NSObject*)giveMeAnObject
{
return [[[NSObject alloc] init] autorelease];
}
-(void)useObject
{
NSObject *object = [self giveMeAnObject];
//use that object
}
but why don't we write like this way 2:
-(NSObject*)giveMeAnObject
{
return [[NSObject alloc] init];
}
-(void)useObject
{
NSObject *object = [self giveMeAnObject];
//use that object
[object release];
}
The Cocoa SDK do things like way 1, I think thats why we all use way 1, it has become a coding convention.
But I just think that if the convention is way 2, we can gain little performance improvement.
So is there any other reason that we use way 1 instead way 2 except coding convention?
Returning an autoreleased object is a form of abstraction -- a convenience for the developer, so he/she does not have to think about the reference counting of the returned object as much -- and consequently results in fewer bugs in specific categories (although you can also say autorelease pools introduce new categories of bugs or complexities). It can really simplify the clients code, although yes, there can be performance penalties. It can also be used as an abstracted optimization when no reference operation must be made - consider when the object holds an instance of what is returned and no retain or copy need be made. Although chaining statements can be overused, this practice is also convenient for chaining statements.
Also, the static analyzer which determines reference count errors is relatively new to some of these libraries and programs. Autorelease pools preceded ARC and static analysis of objc objects' reference counts by many years -- ensuring your reference counting is correct is much simpler now with these tools. They are able to detect many of the bugs.
Of course with ARC, a lot of that changes if you favored the simplicity of returning autoreleased objects -- with ARC, you can return fewer autoreleased objects without the chance of introducing the bugs autorelease pools abstracted.
Using uniform ownership semantics also simplifies programs. If an abstract selector or collection of selectors always return using the same semantics, then it can really simplify some generic forms. For example -- if a set of selectors passed to performSelector: had different ownership-on-return semantics, then it would add a lot of complexity. So uniform ownership on return can really simplify some of the more 'generic' implementations.
Performance: Reference count operations (retain/release) can be rather weighty -- especially if you are used to working in lower levels. However, the current autorelease pool implementations are very fast. They have been recently updated, and are faster than they used to be. The compiler and runtime use several special shortcuts to keep these costs low. It's also a good idea to keep your autorelease pool sizes down -- particularly on mobile devices. Creating an autorelease pool is very fast. In practice, you may see from zero to a few percent increase from the autorelease operations themselves (i.e. it consumes much less time than objc_msgSend+variants). Some tests even ran slightly faster. This isn't an optimization many people will gain much from. It wouldn't qualify as low hanging fruit under typical circumstances, and it's actually relatively difficult to measure the effects and locality of such changes in real programs -- based off some testing I did after bbum mentioned the changes below. So the tests were limited in scope, but it appears to be better/faster in MRC and ARC.
So a lot of this comes down to the level of responsibility you want to assume, in the event you are performing your own reference counting operations. For most people, it shouldn't really change how they write. I think localizing memory issues, more deterministic object destruction, and more predictable heap sizes are the primary reasons one might favor return an 'owning' (+1) reference count if you are running on modern systems. Even then, the runtime and compiler work to reduce this for you in many cases (see bbum's answer +1). Even though autorelease pools are approximately as fast, I don't intend on using them more than I do now at this time -- so there are still justifiable reasons to minimize using them, but the reasons are lessening.
Have you measured the performance benefit? Do you have a quantifiable case where autorelease vs. CF style caller-must-release has a measurable performance impact?
If not, moot point. If so, I'd bet that there is a systemic architecture problem that far eclipses autorelease vs. not.
Regardless, if you adopt ARC, the "cost" of autorelease is minimized. The compiler and runtime can actually optimize away the autorelease across method calls.
There are three main reasons:
It imposes concept of taking ownership.
It eliminates the issues of dangling pointers.
It returns the object created in local auto release pool and so increases performance.
I know this sounds like a dumb question but I need to ask this. Well I read that autorelease pool is drained after one iteration of run loop after it has handled events. My question is that then how come my apps objects are retained after I clicked on button. So, by definition It should destroy all the objects which I have created (may be I have assigned some values to objects) after I click on button. But that doesnt happen ? right ? I can click my button again and again but I dont lose any object data.
Correct me if I am wrong somewhere.
You should watch a video or two from https://developer.apple.com/videos/ - Great introductions to memory management and such. And I also strongly recommend you look into ARC as soon as you grasp the basics of retain/release/autorelease.
All that the autorelease pool does is decrement the retain count of objects in the pool when it is drained. If that results in the retain count becoming zero, the object will be destroyed (dealloc'ed).
However, if an object has been retained more than once, the retain count will be greater than zero so it will not be destroyed (note that objects are created with a retain count of 1.)
What happens when you call -retain on an object many times? Is it OK to just release it once at when you're done using it?
consider the name "reference counting".
you must match each retain with a release (or autorelease).
when reference counting, your program may hold one or more references to an object. you add a reference by retaining the object. when you are done with the object, you forfeit the reference using release or autorelease. when all references are returned, the retain count reaches zero and the object is destroyed.
object lifetimes are also affected by autorelease pools; a convenience mechanism which reduces the number of manual retains/releases as well as reference counting complexity (in some cases). you should read up on autorelease and autorelease pools for a further understanding of this mechanism.
Always remember this three things.
1.) Whenever you pass a retain message to any object, its retain count increases by 1.
2.) And subsequently when you pass a release message to any object, its retain count decreases by 1.
3.) And whenever you are done with the object, always check that its retain count is 0.
Hence, the number of times you retain an object should always be equal to the number of times you release that object.
You can check apple documentation regarding memory management here.
How many times you call this method(retain) that many times Memory is allocated To that Object .you can Get Through Retain Count How many times Object Is being Allocated.
Its creates memory Issues.
If the Object Retain Count Is zero Then That Particular Object IS Not Unavailable to be used for other.
that to If your Retain 10times One Object if U release Once its not being released.
retain Increased by 1 count And Release Decreased by 1. if object having retain count 0 that object is unavailable.
I am just curious with regards to the following, when I am writing code I always try and manage the memory myself by sticking to non-autoreleased objects. I know that this means that objects are not hanging around in the pool, but I was just curious if doing it this way in general is good practice or simply overkill?
// User Managed Memory
NSSet *buttonSizes = [[NSSet alloc] initWithObjects:#"Go", #"Going", #"Gone", nil];
[barItemLeft setPossibleTitles:buttonSizes];
[barItemRight setPossibleTitles:buttonSizes];
[buttonSizes release];
.
// Autoreleased Memory
NSSet *buttonSizes = [NSSet setWithObjects:#"Go", #"Going", #"Gone", nil];
[barItemLeft setPossibleTitles:buttonSizes];
[barItemRight setPossibleTitles:buttonSizes];
Total overkill. If you read the relevant documentation carefully, it does not say that you should avoid autoreleasing objects. It says that you should avoid using autorelease pools when you in tight, object-rich loops. In those cases, you should be managing your memory explicitly (with retain and release) to ensure that objects are created and destroyed in an amortized manner.
The argument that the iPhone is a memory-constrained environment is true, but a complete red herring. Objective-C, with the Foundation and Cocoa frameworks (though they weren't called that at the time), ran just fine on a NeXTcube, which had 16MB of RAM (expandable to 64). Even the iPhone 3, which is pretty much EOL at this point, has 128MB.
edit
Since an iPhone app is a runloop-based application, a new autorelease pool is going to be created and destroyed every time it spins. This is clearly defined in the documentation. As such, the only reasons you'd have to create your own autorelease pool are:
Spawning a background thread, where you must create your own pool (since new threads, by default, do not have a base ARPool)
Performing some operation that will generate a significant number of autoreleased objects. In this case, creating and draining a pool would be to help ensure the limited lifetime of the temporary objects.
However, in the second case, you're recommended to explicitly manage memory as much as possible. This is so that your operation doesn't come to a screeching halt when it attempts to drain a pool with a few thousand objects in it. If you manage your memory manually, you can release these objects gradually as they are no longer needed, instead of saving them up for a single all-at-once release. You could help amortize the all-at-once release by nesting ARPools, which will help.
At the end of the day, though, just do what feels natural, and then (and only then) optimize it if you have concrete evidence that you need to do so.
edit #2
OK, it turns out that there is a recommendation to avoid using autorelease. BUT that recommendation is in the "Allocate Memory Wisely" section of the "Tuning for Performance and Responsiveness" area of the iOS Application Programming Guide. In other words, avoid it if you're measuring a performance problem. But seriously: autorelease has been around for ~20 years and did just fine on computers far slower and more constrained than the iDevices of today.
Unless you see performance issues (or memory issues), I wouldn't worry about using the autorelease pools. Furthermore, autorelease in theory can be more performant than non-auto release. The really dangerous places to use autorelease is in large loops (for example, when importing a large data set). In these cases you can run out of the limited iPhone memory.
I'd recommend you only focus on removing autorelease usage once you've finished your application and can identify memory management issues using the built in instruments.
When possible I like to use the autorelease methods. It eliminates the chance that I forget to release them or somebody comes in and changes the flow of the code so that the explicit release is bypassed. I vote that self-managing the releases is overkill.
It depends on whether or not an autorelease pool is in place. For instance, if you're using objective-c objects in an AudioUnit's render callback (which is called from a separate thread without an autorelease pool) your autoreleased objects will leak. In this case it's important that you release them manually, or wrap them in an autorelease pool.
In general though, I think it's up to you and your coding style
There's a balance. It depends a lot on the situation. In that particular case, assuming the barItem* variables are long-lived ivars, avoiding autorelease is pretty close to 100% pointless, because the set will be sticking around regardless of whether you release it now or two seconds from now.
In fact, in most cases, it makes little difference whether objects are released now or on the next iteration of the runloop, because the runloop is going so fast that it's actually capable of creating smooth animation. The iPhone is a particularly memory-starved platform, so it's good not to leave things alive too long. But at the same time, be realistic: One autoreleased NSNumber in a method that's called every couple of seconds isn't even going to make a dent in your app's profile. Even 100 thousand-character NSStrings will only use about 0.065% of the system RAM on an iPhone 3GS. That only becomes significant when you build up a ton of them in a very short time. So if there's no problem, don't sweat it.
I think there is only one resonable answer: usually autorelease is not an performance issue. It is good to keep in mind that it could be problematic in tight loops, but unless a performance meter like Instruments shows a memory spike you have to get rid of, I would use it if you like.
Premature optimization is a great way of spending time for nothing. Maybe in the end you know that your solution is elegant, but it could be that the easier solution performs just as fine.
under the "Guaranteeing the Foundation Ownership Policy" in Apple developer's site article on Autorelease pool
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-997594, they talk about extending an object's lifetime beyond the Autorelease pool.
Can someone give me a situation where this concept could be used?
Short answer: What the documentation is saying is that if you need to keep an object that has been autoreleased in an autorelease pool, you need to retain it.
Long answer: For instance, say I need to do a certain operation to 1000 objects. Once I'm done with these objects I'm going to autorelease them. Without an autorelease pool, they're going to be eventually released, but holding those 1000 objects in memory can make your program really slow (at least until they're autoreleased).
In order to solve this issue, I'm creating an autorelease pool that will be cleaned every 100 objects. However, what happens if I need to keep the last object of the last batch around? I still need to purge those other 99 objects. What I'm going to do is send a retain message to that very last object then clean the autorelease pool.
This way the autorelease pool will notify the system that it no longer wants those 100 items, but you've already let the system know that you do need one of them. If the object had a previous retain count of 1, then it'll still be around:
1 (original retain count) +1 (your retain) -1 (autorelease pool release) = 1.
This preserves the object after the autorelease pool is done with it.