autoreleasepool inside a method on ARC - iphone

I am wondering if there's any benefit of using #autoreleasepool on an ARC code inside a method.
I mean this. Suppose I have a memory intensive method that is called several times in sequence. Something like
// this is my code
for (id oneObject in objects {
[self letsUseMemory];
}
and then
- (void) letsUseMemory {
// heavy use of memory here
}
and I do this
- (void) letsUseMemory {
#autoreleasepool {
// heavy use of memory here
}
}
Is there any benefit? I mean, the method variables will be deallocated anyway when the method finishes, so adding an autoreleasepool there, in theory, will do any benefit, right?
Or will autoreleasepool inside that method speed the deallocation?
thanks.

Is there any benefit? I mean, the method variables will be deallocated anyway when the method finishes, so adding an autoreleasepool there, in theory, will do any benefit, right?
It depends. Any autoreleased temporary objects will not be deallocated until the pool drains, regardless of whether you're using ARC. I.e.:
NSString* foo = [NSString stringWithFormat:#"Bar: %#", baz];
Without an enclosing #autoreleasepool, that object instance may hang around until you return to the run-loop. If that line of code exists within a loop, you may be accumulating a large number of these temporary objects.
The general rule of thumb is that if you have a potentially large loop that may create autoreleased objects, wrap the inside of the loop in with an #autoreleasepool.
It's less common and perhaps somewhat meaningless to wrap a single method in an #autoreleasepool because it would usually only have meaningful effect if the method was called many times in a loop. Putting the #autorelease pool in the loop makes the intent more clear.

There are a number of "it depends" things going on there, I believe.
Starting with the obvious, if there are no autoreleased objects, it doesn't matter. If your code goes right back to the run loop after your enumeration finishes, it doesn't matter.
That leaves the case where the method containing the enumeration is used to do a bunch of initialization and then continues on with more processing. For that one, you could benefit by getting rid of temporary objects that were marked for later release.

Related

Does passing an object as a parameter for a method increment its retain counter under ARC? [duplicate]

When compiling with ARC, method arguments often appear to be retained at the beginning of the method and released at the end. This retain/release pair seems superfluous, and contradicts the idea that ARC "produces the code you would have written anyway". Nobody in those dark, pre-ARC days performed an extra retain/release on all method arguments just to be on the safe side, did they?
Consider:
#interface Test : NSObject
#end
#implementation Test
- (void)testARC:(NSString *)s
{
[s length]; // no extra retain/release here.
}
- (void)testARC2:(NSString *)s
{
// ARC inserts [s retain]
[s length];
[s length];
// ARC inserts [s release]
}
- (void)testARC3:(__unsafe_unretained NSString *)s
{
// no retain -- we used __unsafe_unretained
[s length];
[s length];
// no release -- we used __unsafe_unretained
}
#end
When compiled with Xcode 4.3.2 in release mode, the assembly (such that I'm able to understand it) contained calls to objc_retain and objc_release at the start and end of the second method. What's going on?
This is not a huge problem, but this extra retain/release traffic does show up when using Instruments to profile performance-sensitive code. It seems you can decorate method arguments with __unsafe_unretained to avoid this extra retain/release, as I've done in the third example, but doing so feels quite disgusting.
See this reply from the Objc-language mailing list:
When the compiler doesn't know anything about the
memory management behavior of a function or method (and this happens a
lot), then the compiler must assume:
1) That the function or method might completely rearrange or replace
the entire object graph of the application (it probably won't, but it
could). 2) That the caller might be manual reference counted code, and
therefore the lifetime of passed in parameters is not realistically
knowable.
Given #1 and #2; and given that ARC must never allow an object to be
prematurely deallocated, then these two assumptions force the compiler
to retain passed in objects more often than not.
I think that the main problem is that your method’s body might lead to the arguments being released, so that ARC has to act defensively and retain them:
- (void) processItems
{
[self setItems:[NSArray arrayWithObject:[NSNumber numberWithInt:0]]];
[self doSomethingSillyWith:[items lastObject]];
}
- (void) doSomethingSillyWith: (id) foo
{
[self setItems:nil];
NSLog(#"%#", foo); // if ARC did not retain foo, you could be in trouble
}
That might also be the reason that you don’t see the extra retain when there’s just a single call in your method.
Passing as a parameter does not, in general, increase the retain count. However, if you're passing it to something like NSThread, it is specifically documented that it will retain the parameter for the new thread.
So without an example of how you're intending to start this new thread, I can't give a definitive answer. In general, though, you should be fine.
Even the answer of soul is correct, it is a bit deeper than it should be:
It is retained, because the passed reference is assigned to a strong variable, the parameter variable. This and only this is the reason for the retain/release pair. (Set the parameter var to __weak and what happens?)
One could optimize it away? It would be like optimizing every retain/release pairs on local variables away, because parameters are local variables. This can be done, if the compiler understands the hole code inside the method including all messages sent and functions calls. This can be applied that rarely that clang even does not try to do it. (Imagine that the arg points to a person (only) belonging to a group and the group is dealloc'd: the person would be dealloc'd, too.)
And yes, not to retain args in MRC was a kind of dangerous, but typically developers know their code that good, that they optimized the retain/release away without thinking about it.
It will not increment behind the scenes. Under ARC if the object is Strong it will simply remain alive until there are no more strong pointers to it. But this really has nothing to do with the object being passed as a parameter or not.

Return Statement Creates and Release an Object

I'm working someone else's code. I've never encountered something like this before:
return [[[NSObject alloc] init] autorelease];
Can someone tell me what this means and why someone would use it? Just to be clear, I'm not asking about the autorelease portion. I would have the same question about this code:
-(id)someMethod
{
lots of lines of code
...
return [[NSObject alloc]init];
}
The autorelease feature indicates that you want to release this object in the FUTURE, but not now because you still need to access it. With the release cycles and releasing of the pool of memory, autorelease is an extremely useful tool in memory management.
You can refer to: http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447 for information on autoreleasing.
Here's a link! What is the difference between releasing and autoreleasing?
Hope this helped!
The object is being allocated, initialized and then added to an autorelease pool.
Quoting Apple documentation (the link above):
Autorelease pools provide a mechanism whereby you can send an object a
“deferred” release message. This is useful in situations where you
want to relinquish ownership of an object, but want to avoid the
possibility of it being deallocated immediately (such as when you
return an object from a method). Typically, you don’t need to create
your own autorelease pools, but there are some situations in which
either you must or it is beneficial to do so.
TL;DR if nobody will retain the object soon, it will be released on the next iteration of the run loop.
It's hard to tell without knowing any details why would anyone want to allocate an NSObject in the first place. I'd suggest searching the project for that method's usage examples and see what happens with the object next.
It is just returning an autoreleased object for convenience. This means that when you use the function you do not have to append autorelease message to it generally speaking. You may always want certain objects to be autoreleased.
As an example, many of the included convenience ("factory") methods in Objective-C return an autoreleased object. You are probably familiar with [NSString stringWithFormat:__FORMAT__] which returns an autoreleased NSString. Take a look at http://memo.tv/archive/memory_management_with_objective_c_cocoa_iphone
As an example of why a function might return an object, consider a synchronous URL request, where you may or may not care about a response, or a function like the following:
- (NSString *)modifyObject:(MyObject *)o {
o.mySettableProp = #"MODIFIED!";
return [o description];
}

#autoreleasepool in loop or loop in #autoreleasepool?

It's a good practice to put lots of autoreleased object in an autoreleasepool at loop action. I found someone put the #autoreleasepool in loop but others put loop in #autoreleasepool.
1:
while ([rs next]) {
#autoreleasepool {
NSDictionary *dict = [self dictFromXX];
//...
}
}
2:
#autoreleasepool {
while ([rs next]) {
NSDictionary *dict = [self dictFromXX];
//...
}
}
Which is better? or any difference between code 1 and 2?
Thanks!
In your first example for every iteration the pool is drained. This makes sense if the body of the iteration involves a lot of autoreleased objects.
The second example will only drain the pool once after the loop.
So if the internals of the loop are causing the memory bloat then go for option one. If the memory bloat over the whole loop is acceptable then loop then use option two.
In the first example autoreleasepool is created at the beginning of iteration and is drained and the end of iteration.
In the second case pool is created once and is destroyed only after the loop is finished. If you use the second variation then you can get a big memory overhead since all autoreleased objects are freed only at the end. However you should consider the amount of data you need to process. In most cases the second variant is more preferred.
I would go for version 2.
A #autoreleasepool block will release all objects that received a autorelease when the block was finished. This will take time because it will need some cpu cycles and depending on the object, the used time can be much higher then expected.
I think custom #autoreleasepools only make sense when working with many data > 20MB or working with Data in a non-main-thread.
So. I recommend to avoid "short" #autoreleasepool's. Because it may slow down your execution.
Here is a different approach with Core Data an autoreleasepools:
Testing Core Data with very big hierarchical data sets of Efficiently Importing Data
important for you is the Wrap the contents of the outer loop in an NSAutoreleasePool init/release and NSManagedObjectContext save solution.
Depend on how many pending items will be released. Image that Autorelease Pool like your trash, put unused thing and will throw later.
#autoreleasepool blocks are more efficient than using an instance of NSAutoreleasePool directly; you can also use them even if you do not use ARC. - NSAutoreleasePool Class Reference
You generally do not need autorelease pools, if you do because you are in a loop and autoreleasing lots of objects then option 1 makes more sense than 2 as you are trying to avoid the spike that the loop is creating. The time to use option 2 is if there isn't an autorelease pool set up (if you are performing a selector in the background for example or in +load), but you should really try to use GCD for those anyway.
In summary, if you do not have a very long method and you need to wrap a loop in a autorelease pool, go for option 1 in most cases. If the method is being called without an autorelease pool having been set up then #autorelease needs to be the first thing.

Use autorelease before adding objects to a collection?

I have been looking through the questions asked on StackOverflow, but there are so many about memory management in Objective-C that I couldn't find the answer I was looking for.
The question is if it is ok (and recommnded) to call autorelease before adding a newly created object to a collection (like NSMutableArray)? Or should I release it explicitly after adding it. (I know NSMutableArray willl retain the object)
This illustrates my question:
Scenario A (autorelease):
- (void) add {
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
}
Scenario B (explicit release):
- (void) add {
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
[obj release];
}
I assume both are correct, but I am not sure, and I sure don't know what the preffered way is.
Can the Objective-C gurus shed some light on this?
IMHO, which way is 'right' is a matter of preference. I don't disagree with the responders who advocate not using autorelease, but my preference is to use autorelease unless there is an overwhelmingly compelling reason not to. I'll list my reasons and you can decide whether or not their appropriate to your style of programming.
As Chuck pointed out, there is a semi-urban legend that there's some kind of overhead to using autorelease pools. This could not be further from the truth, and this comes from countless hours spent using Shark.app to squeeze the last bit of performance out of code. Trying to optimize for this is deep in to "premature optimization" territory. If, and only if, Shark.app gives you hard data that this might be a problem should you even consider looking in to it.
As others pointed out, an autoreleased object is "released at some later point". This means they linger around, taking up memory, until that "later point" rolls around. For "most" cases, this is at the bottom of an event processing pass before the run loop sleeps until the next event (timer, user clicking something, etc).
Occasionally, though, you will need to get rid of those temporary objects sooner, rather than later. For example, you need to process a huge, multi-megabyte file, or tens of thousands of rows from a database. When this happens, you'll need to place a NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; at a well chosen point, followed by a [pool release]; at the bottom. This almost always happens in some kind of "loop batch processing", so it's usually at the start and bottom of some critical loop. Again, this should be evidence based, not hunch based. Instrument.app's ObjectAlloc is what you use to find these trouble spots.
The main reason why I prefer autorelease to release, though, is that it is much easier to write leak-free programs. In short, if you choose to go the release route, you need to guarantee that release is eventually sent to obj, under all circumstances. While this seems like it might be simple, it is actually surprisingly hard to do in practice. Take your example, for instance:
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
// Assume a few more lines of work....
[obj release];
Now imagine that for some reason, something, somewhere, subtly violates your assumption that array is mutable, maybe as the result of using some method to process the results, and the returned array containing the processed results was created as a NSArray. When you send addObject: to that immutable NSArray, an exception will be thrown, and you will never send obj its release message. Or maybe something goes wrong somewhere between when obj was allocd and the required call to release, like you check some condition and return() immediately by mistake because it slipped your mind that that call to release later on must take place.
You have just leaked an object. And probably signed yourself up to several days of trying to find out where and why it is your leaking it. From experience, you will spend many hours looking at that code above, convinced that it could not possibly be the source of the leak because you very clearly send obj a release. Then, after several days, you will experience what can only be described as a religious epiphany as you are enlightened to the cause of the problem.
Consider the autorelease case:
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
// Assume a few more lines of work....
Now, it no longer matters what happens because it's virtually impossible to leak obj accidentally, even under extremely unusual or exceptional corner cases.
Both are correct and will work as you're expecting them to.
I personally prefer to use the latter method, but only because I like to be explicit about when objects get released. By autoreleasing the object, all we're doing is saying "this object will get released at some arbitrary point in the future." That means you can put the autoreleased object into the array, destroy the array, and the object might (probably) still exist.
With the latter method, the object would get destroyed immediately with the array (providing that nothing else has come along and retained it in the meantime). If I'm in a memory-constrained environment (say, the iPhone) where I need to be careful about how much memory I'm using, I'll use the latter method just so I don't have so many objects lingering in an NSAutoreleasePool somewhere. If memory usage isn't a big concern for you (and it usually isn't for me, either), then either method is totally acceptable.
They are both correct but B may be preferred because it has no overhead at all. Autorelease causes the autorelease pool to take charge of the object. This has a very slight overhead which, of course, gets multiplied by the number of objects involved.
So with one object A and B are more or less the same but definitely don't use A in scenarios with lots of objects to add to the array.
In different situations autoreleasing may delay and accumulate the freeing of many objects at the end of the thread. This may be sub-optimal. Take care that anyway autoreleasing happens a lot without explicit intervention. For example many getters are implemented this way:
return [[myObject retain] autorelease];
so whenever you call the getter you add an object to the autorelease pool.
You can send the autorelease message at any point, because it isn't acted on until the application's message loop repeats (i.e. until all your methods have finished executing in response to user input).
http://macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=last&x-showcontent=text
You have alloc'ed the object, then it's your job to release it at some point. Both code snippets work merely the same, correct way, with the autorelease way being the potentionally slower counterpart.
Personally speaking, I prefer the autorelease way, since it's just easier to type and almost never is a bottleneck.
They're both OK. Some people will tell you to avoid autorelease because of "overhead" or some such thing, but the truth is, there is practically no overhead. Go ahead and benchmark it and try to find the "overhead." The only reason you'd avoid it is in a memory-starved situation like on the iPhone. On OS X, you have practically unlimited memory, so it isn't going to make much of a difference. Just use whichever is most convenient for you.
I prefer A (autoreleasing) for brevity and "safety", as johne calls it. It simplifies my code, and I've never run into problems with it.
That is, until today: I had a problem with autoreleasing a block before adding it to an array. See my stackoverflow question:
[myArray addObject:[[objcBlock copy] autorelease]] crashes on dealloc'ing the array (Update: Turns out the problem was elsewhere in my code, but still, there was a subtle difference in behavior with autorelease…)

iphone memory management

I have a method that returns a NSMutableArray:
//implementation of class Students
-(NSMutableArray *)listOfStudents {
NSMutableArray *students = [[NSMutableArray alloc] init];
//add objects to students and other operations here
return students;
}
The problem here is, when and where do I release the object students? If it was an instance variable, I would add a [students release] in the dealloc method, but it's not. The class Students allocated the object, so it owns the new NSMutableArray and it must release it, right?
Since I can't release it before return it, the only option I see here is... return it as:
return [students autorelease];
But it doesn't feel right to use autorelease objects on the iPhone. This method will be called many times... and I would like to release the memory as soon as possible. Also, the autorelease pool is in the main function and it looks like it will take a while to clean the mess.
How would you do it?
I tend to avoid using autorelease wherever I can within my iPhone applications, but there are some cases where it doesn't hurt you that much. If the array that you're generating via this method will be retained for a reasonably long duration, then you won't be sacrificing any performance or memory usage by returning it as an autoreleased result.
However, if you will be using and discarding the returned object quite frequently, you may wish to do something different. I have a naming convention with my methods that if something is prefixed by "generate", like generateStudentsArray, it returns an object that is owned by the caller and must be manually released (like with copy). This helps to avoid using autoreleased objects, but it adds another thing to remember when doing memory management.
Additionally, because memory allocation / deallocation is costly (especially on the iPhone), you may wish to avoid the frequent allocations and deallocations within a method called quite a lot and instead recycle the mutable array by creating it ahead of time and passing it into the method, which only adds to the array's contents.
You're right, autorelease is the standard idiom to use in a situation like this.
UIKit actually creates an autorelease pool at the start of each event cycle and releases it at the end, so your autoreleased objects will get cleared up then; they won't be hanging around forever.
If you had a loop that was calling this method many times within a single event cycle, you might want to create your own autorelease pool inside that loop so that these objects get released at the end of each iteration, rather than building up loads of objects to be released at the end of the current event cycle.
But unless you're doing something like that, or you are encountering another specific out-of-memory situation, UIKit's standard autorelease pools should handle it fine.