tbag
tbag

Reputation: 1278

Reduce the memory usage of an iPhone application

We are in process of making a game for an iPhone. We are done with the development and trying to optimize the game now for memory. We are noticing that when we load a particular MVC in the game an close it, not all of the allocated memory is freed up.(~ 4-5MB is added). This drives the memory usage of the game really high if you keep playing it for 15-20 mins and the game finally crashes after giving a low memory warning.

This is what I have tied
1. Run the static analyzer on the game and fixed all memory leaks and warnings.
2. Manually checked if the dealloc of all classes is getting called. This seems to be fine.
3. Also tried running the Allocations tool in Xcode, but most of the entries in it are CFStrings, mallocs and CFNumbers etc but doesnt really tell which of my classes they originate from. Is there a better way to use the allocations tool?

I also have a couple of memory related questions
1. We are using autorelease objects in many places in the game without using an autorelease pool. My understanding is autoreleased objects should free up in the next run loop and should not pose such a huge problem?
2. Also if I load images through xib files are they cached by iOS. Will they be hogging the memory too?

How do I go about solving my memory usage issues. Any help would be appreciated. Thanks!

Upvotes: 3

Views: 2601

Answers (3)

bbum
bbum

Reputation: 162712

What Rob and Chris said, then do this:

Use the Allocations instrument configured to only track active allocations and to record reference counts.

Use your app a bit while Allocations gathers data, then pause your application.

While paused, sorting by Live Bytes and # Living are your most useful views. For a data centric application that leverages the Foundation collection classes, it is likely that some combination of *String, *Dictionary, and *Array will be the most common.

That is OK. If you click through to the details about any one of those, you'll get a long list of all the instances currently in memory. You could po <addr> any one of them to see what they are. And you can also scroll through the list to see what functions are most commonly responsible for the allocation. As well, you can click through to any instance to see where it was allocated and/or why it might still be around.

As well, you can start with the overview table, sort by #Living, and scroll down to the first instance of one of your classes. If that class roots -- holds onto -- a lot of data, then eliminating or optimizing that is a great start.

And, of course, don't forget heapshot analysis as an exceptionally effective tool for generational analysis of memory growth.

Upvotes: 2

Rob
Rob

Reputation: 437392

A couple of thoughts:

  1. Are you using Core Foundation classes? Make sure that for every object for which you have a Core Foundation call with Create or Copy in the name that you call CFRelease (or transfer ownership and then release or autorelease the Objective-C object).

  2. Have you used the Leaks tool in Instruments, too? I assume so, but you didn't mention it. See Finding Leaks in your App in the Instruments User Guide.

  3. Are you loading images via imageNamed? That caches images and is not good about releasing them. It's safer to use imageWithContentsOfFile and manage your cache manually.

  4. I assume your view controller's dealloc is getting called and that you're releasing all of the objects associated with the class properties/ivars?

  5. Do you have zombies turned on? That's great for diagnostic purposes, but you won't release memory until you turn off zombies.

Upvotes: 4

Chris Wagner
Chris Wagner

Reputation: 20993

If you are "in the process" of making something, you should be using ARC (automatic reference counting). Once you are all converted to ARC you will no longer need those autorelease objects and the compiler will release objects at the appropriate times. If you find that you have a situation where a pool of objects are still growing out of control you can create your own autorelease pool using the @autoreleasepool declarative.

I think switching to ARC will help you out and make your further development much simpler. Profile your App again in Instruments after converting to ARC and narrow down on any offending code that is creating large pools of objects.

If you choose not to convert to ARC, based on your explanation, it sounds like you could have a retain cycle with the view you are referring to. Make sure that view is actually being released by tracing down every place it is retained.

Upvotes: 2

Related Questions