when should I wrap my code into autorelease pool
Asked Answered
A

4

9

I am a new to objective-c, and I know the basic memory management rules like when to retain release autorelease. But I don't know when should I wrap my code into autorelease pool and why?

Auston answered 13/5, 2012 at 16:36 Comment(0)
R
21

As with other performance optimizations, you should generally only add additional autorelease pools to your code if you notice high memory usage and profiling (using Instruments, for example) leads you to additional autorelease pools as a solution.

That said, you can wrap code that creates a large number of temporary objects in a tight loop in an autorelease pool. The default autorelease pool is drained at the end of a run loop cycle. So, if you're creating lots of temporary objects in each iteration of a for loop in your code, the default autorelease pool won't be drained until after your entire loop has run, meaning all the temporary objects you create can add up to a high temporary memory usage (sometimes called the "high water mark"). You can wrap each iteration of the loop in an @autoreleasepool to cause unneeded, autoreleased, temporary objects created in that loop iteration to be released sooner.

Ritchey answered 13/5, 2012 at 16:39 Comment(3)
You saved me. I have a long running calculation method creating lots of numbers in several loops. In instruments the memory usage is climping up tremendously and dropping after the calculation finishes. Is there a drawback using @autorelease for wrapping single loops? It's not really recommended by Apple, isn't it?Extinction
It is recommended by Apple in cases where it's appropriate. See the documentation here: developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/…Ritchey
Andrew, you are just awesome! I had an headache because of that memory issue until I found that suggestion. It is simple and works just awesome. I can even allow more calculations in my app now. THANKS!Extinction
T
12

To extends the previous answers:

An auto-release pool is used to send a release message automatically to objects added to it.

In a iOS or Cocoa program, an auto-release pool is automatically created on the main thread, and it's drained at the end of the run loop.

That said, an auto-release pool is mandatory when using auto-released objects on another thread.

So if you detach a thread to some method, then wrap your threaded code inside an auto-release pool. Otherwise, the auto-released objects created in the thread will just leak.

Another use of an auto-release pool is the optimization of parts of code that will use a lot of memory, so they are freed before the end of the run loop.

But it only concerns auto-released objects.

For instance:

- ( void )test
{
    NSMutableArray * a = [ [ NSMutableArray alloc ] init ];

    [ a release ];
}

No need for an auto-release pool here, as you don't have an auto-released object.
The a variable will be freed immediately, as it was explicitly allocated, and released.

Now this:

- ( void )test
{
    NSMutableArray * a = [ NSMutableArray arrayWithCapacity ];
}

Here you are using a convenience constructor, meaning you don't have the ownership on that object.
It also means the object was added to the current auto-release pool (if there's one).

So it will be freed when this auto-release pool is drained, so it might take some cycles...

If the portion of the code you are writing uses a lot of memory, you may use another auto-release pool, so your auto-released objects are freed when your method returns:

- ( void )test
{
    @autoreleasepool
    {
        NSMutableArray * a = [ NSMutableArray arrayWithCapacity ];
    }
}
Typhoid answered 13/5, 2012 at 17:3 Comment(0)
V
1

All autoreleased objects are technically put inside an autorelease pool. There is usually a default one created inside your main function. As for wrapping objects within a non-default autorelease pool, that is usually done as an optimization.

There is usually no need to use an explicit autorelease pool because the default autorelease pool is drained automatically within your app's run loop. However, if you have an app that creates many autoreleased objects before it returns from your event handlers, it can use a lot of memory for those objects. So if you wrap your code inside an explicit autorelease pool, the autoreleased objects will be placed there rather than the default pool. This allows you to periodically empty this pool to prevent the autoreleased objects from accumulating.

Venetic answered 13/5, 2012 at 16:52 Comment(0)
L
0

There are, however, three occasions when you might use your own autorelease pool blocks:

  1. If you are writing a program that is not based on a UI framework, such as a command-line tool.

  2. If you write a loop that creates many temporary objects. You may use an autorelease pool block inside the loop to dispose of those objects before the next iteration. Using an autorelease pool block in the loop helps to reduce the maximum memory footprint of the application.

  3. If you spawn a secondary thread.

Lotz answered 4/9, 2013 at 23:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.