#autoreleasepool in loop or loop in #autoreleasepool? - iphone

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.

Related

autoreleasepool inside a method on ARC

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.

How can I keep memory usage low with a lot of NSStrings, or how do I release NSStrings?

I am working on an app that imports a (very) large csv file into Core Data for catching purposes. The process goes something like this:
Parse the file line-by-line into an NSMutableArray full of NSStrings
After X number of lines, import the array into Core Data (this involves manipulating and in some cases creating new NSStrings)
[NSMutableArray removeAllObjects];
Rinse and repeat
At first glance it looks like the memory should be freed up at the conclusion of each cycle. With large files, however, I am finding that the app crashes after signaling a couple low memory warnings. Running the leaks tool tells me that most of the memory is being used up by CFString objects, which I understand are related to NSString objects (although I don't know how)
I understand that NSString are reused whenever possible, and that they don't act quite the same as other objects where memory is concerned, although I don't understand any of the details. How can I reclaim the memory that my NSString objects are using?
Running the leaks tool tells me that most of the memory is being used up by CFString objects, which I understand are related to NSString objects (although I don't know how)
NSString is actually a class cluster. Although you think you are working with NSStrings, you are almost certainly really working with one of its subclasses. The Cocoa framework chooses which subclass to use depending on circumstances.
CFString is actually not really an NSString at all, it is the pure C string object used by Core Foundation. However, you'll find it is "toll free bridged" to NSString. This means that, to Cocoa, it looks like an NSString. The reason you are seeing lots of CFString usage is because whatever Cocoa API you are using to obtain these strings ultimately performs its work in Core Foundation.
Anyway, all that is irrelevant to your problem except for the fact, that lots of CFStrings more or less means the same as lots of NSStrings. What you need to reduce your memory footprint is nested autorelease pools as Girish has already said. As a first step, modify your algorithm like this:
Create a new autorelease pool.
Parse the file line-by-line into an NSMutableArray full of NSStrings
After X number of lines, import the array into Core Data (this involves manipulating and in some cases creating new NSStrings)
[NSMutableArray removeAllObjects];
drain the autorelease pool
Rinse and repeat (start at 0)
If this doesn't help, or only helps a bit, consider bracketing just the parsing with an autorelease pool.
I am assuming that you don't have memory leak.
If you are using too much autoreleased object this can happen
You try following
Create nested auto release pools --- some time happen that you have some long running loops where auto release object get accumulated. -- so add custom auto release pool to release the auto release object when you required.
Don't use autorelease object in the parsing cycle --- do manual object allocation and release once your work is done.
You can't sure that the memory is consumed by NSStrings only. I suggest you check it thoroughly. Try to go for "Build and Analyze" it will help you to find out leaks.
While using NSString object, instead of going for autoreleased objects like
[NSString stringWithFormat#""];
create your own object and release it as soon as you done with it.
NSString * string = [[NSString alloc]initWithFormat:#""];
//use string object
[string release];
this way you can be sure, that you releasing the string there itself.
or create an Autorelease pool
NSAutoReleasePool * pool = [[NSAutoReleasePool alloc]init];
// do you coding, creation of objects, releasing them, whatever...
[pool drain]; or [pool release];
Also have a look at these memory management tips

How often should I put NSAutoreleasePools in place?

Hey, I am making a cocoa touch static library, And I have this problem:
I am running my project in the simulator with the Leaks instrument, And I am coming up with leaks for autoreleased objects.
I know for a fact that I have at least one NSAutoreleasePool in place at a time (in my main() method), my question is, how often should I put in others (I am developing for iPhone and iPad if that matters)
UPDATE: I have figured out that, for some reason, my code isn't exiting out of the UIApplicationMain() call on iOS 4, I am just getting a SIGKILL signal, and my autorelease pool isn't draining. How can I fix that (I mean the app getting a SIGKILL)
Thanks
NSAutoreleasePool is required when you run something in a background thread, so if your functions can be run in a background then you need to create a autorelease pool in them:
- (void) willRunInBackground{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
...
[pool drain];
}
The second situation where NSAutoreleasePool will be useful is when you create many autoreleased objects in a loop - to avoid to much autoreleased objects hanging around you can create and drain autorelease pool on loop iteration (as Joe mentioned).
But you memory leaks are likely caused by the 1st reason - each thread must have its own NSAutoreleasePool to handle autoreleased objects.
The fact that you are autoreleasing objects does not, in itself, prevent a memory leak. Since you're not seeing messages in Console telling your that your objects are being autoreleased outside a pool, it indicates that the problem isn't that they're not being put into a pool.
You must not be managing your retain count properly. Remember that all calls to -alloc and -copy must be balanced by calls to -release or -autorelease. Perhaps you aren't releasing your member variables in a class's dealloc method somewhere. Start by using Instruments to find where you are allocating / copying your objects, then look at every place you retain and release them to ensure each object's retain count is balanced.
From the WWDC videos standard practice holds that a tight loop with a lot of variables flying around is a good place to put one. Start it before the loop, everything in the loop that is autoreleased should go to that pool, and drain it afterward.

Suggest the best way of initialization of array ( or other objects )

I am a bit confused in the following two ways of initialisations.....
Way 1:
- (void) myMethod{
NSArray *myArray = [[NSArray alloc] initWithObjects:obj1,obj1,nil];
[self setClassArray:myArray];
[myArray release];
}
Way 2:
- (void) myMethod{
NSArray *myArray = [NSArray arrayWithObjects:obj1,obj2,nil];
[self setClassArray:myArray];
}
In way 1, I have used a alloc init method which is a instance method and as I have used an alloc statement I have to release the array myself.
In way 2, I have used a static method to initialze the array and as there is no alloc statement used I dont need to release the memory the system will take care of that.
Way 1, is time consuming and can to lead to memory leaks if not taken care
Way 2, is faster in writing and you dont need to take care of memory leaks
But , still i have seen the way1 used in standard source codes more often than the way2. I have no idea why people do this or if I am wrong at some place.
Answers and comments are oppenly invited. Please suggest the best programming practice.
Your second example uses a convenience constructor, which returns an autoreleased object. The question, then, is whether it's better to use autorelease or alloc/release. mmalc's answer on this StackOverflow thread explains the drawbacks of autoreleasing objects. (Basically, use alloc/release whenever possible.)
Also (this may be stating the obvious), some classes might not have convenience constructors, so when working with these you'd have to use alloc/release.
as i know,
[NSArray arrayWithObjects:obj1,obj2,nil];
returns an autoreleased object, smth like
[[[NSArray alloc] initWithObjects:obj1,obj1,nil] autorelease];
and I prefer not to manage memory with autorelease pool. maybe it's just a prejudice))
When using method 2 (autorelease) the object is released when the operating system feels it has no references.
But when using the manual release, as you typed in your code, you can release directly, or whenever you need to.
I usually prefer the second way, and if I recall correctly, this is also what the Apple docs reccommend (use autorelease where possible).
In Way 1 the memory gets released faster, so if you have a method that gets called in a loop or recursively, using autorelease may accumulate much memory, whereas alloc/retain will keep your memory footprint low.
On the other hand I assume that using autorelease is more efficient, because the autorelease pool can release a big chunk of memory at once, instead of small chunks again and again. Tough I may be wrong here.

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.