iPhone Development - Memory limitation for iphone application - iphone

Can anyone point into the right direction here. I want to respond when my application receives memory warning, (i want to know how to respond to this notification). Plus, How much memory can i wire with my application?
Any articles or book reference would be great. Thanks.

If your app gets a memory warning (such as in your view controller's didReceiveMemoryWarning method) you need to release any non-critical data. Anything that you're using that cached, for example, or that can be regenerated, should be dumped.
For example, if your app crunches some numbers and stores the result in a big array, if you're not actively using that array, you should release it. Then, regenerate it when you need it again.
A little more information is here:
Observing Low-Memory Warnings

I've heard informally that warnings get issued when your application hits about 22 MB. (Any allocated memory is included -- the iPhone keeps everything in physical RAM and doesn't page out to any other storage.) Given that the phone only has 128 MB of total RAM, this seems plausible.
That limit does not include the memory used by shared system libraries, such as the Objective-C runtime. And while I'm not entirely sure on this, I don't think WebKit's memory usage is included for the UIWebView component, as I believe WebKit is always loaded (but again, not 100% sure on that).
The best thing to do when you hit this limit is free anything that you can easily regenerate or re-read from input files, such as views, images, and cached data.

Related

What are Recommended Ways to Optimize Memory and Usability Speed of custom UITableViewCells with multiple UIImages?

I am using a custom UITableViewCell with 3 UIImages in a UITableView with 50-100 rows. Its similar to a UITableViewCell the Facebook iPhone app uses for its news feed view.
The application has 4 similar UITableViews which may be open at the same time via a UITabConroller.
The images are lazy loaded, there is a cache on disk so that no images are loaded twice from the server and there is also a NSMutableDictionary for images allowing in-memory reuse of the same image eg: a users profile picture appears multiple times
This setup is extremely fast but takes a lot of memory even after using the NSMutableDictionary for image reuse.
I tried a variation without the NSMutableDictionary where images are either loaded from the server or pulled from the disk cache every time cellForRowAtIndexPath is called. This setup is extremely memory efficient but causes a noticeable lag in the UITableView scrolling.
A mid-way approach is to free the NSMutableDictionary for images when a low memory warning is received.
Will really appreciate recommendations to optimize memory usage and speed in this scenario and or an insight into how the Facebook iphone app or three20 execute this conceptually.
I have an app that is very similar to yours in many respects (uses Three20, has several tabs across the bottom, each tab can have a table, each cell can have one or two images); and the approach I'm taking is the one you mentioned near the end of your post:
A mid-way approach is to free the NSMutableDictionary for images when a low memory warning is received.
Personally, I quite like iOS's approach to memory management, of warning me when memory is getting tight. The Mac/PC approach of "just use all the memory you want, we'll swap it out to disk if memory gets tight" has the disadvantage that even though the OS is the only one who really knows how much pressure there is on memory, it isn't telling you. I think what every polite app would really like to say (if apps could talk) is, "I'd be happy to use as much memory as you'll give me, but I don't want to be a bother, I don't want to slow down any other apps, so if you could please give me a hint as to how much memory I can use without causing problems, I would appreciate it."
Well that's what iOS's memory warnings give you, in my opinion. So, just keep as many images cached in memory as you want; and when you get a memory warning, empty the in-memory cache. To me it's really the best of both worlds.
Also, you should definitely take a look at Three20's TTURLCache, although I can't tell you a lot about it because I haven't dug into it very much. What I do know is:
If you retrieve your messages via TTURLImageResponse, it will automatically cache them in TTURLCache's image cache.
You can also store and load your own images (and other data) in the TTURLCache.
Three20 seems to take an approach similar to what I am talking about. Take a look at this code from Three20Network/Sources/TTURLCache.m (the NO argument means don't remove from disk, only remove from memory):
- (void)didReceiveMemoryWarning:(void*)object {
// Empty the memory cache when memory is low
[self removeAll:NO];
}
In addition, that class also allows you to set a maximum size for the in-memory cache, but by default there is no maximum size.
you would purge images when they go offscreen, then read the images from the locale cache on demand from a secondary worker thread when needed. since one can zip through tables, add support for read cancellation (esp. for requests which come off the server). NSOperation is a good api for this.
if you know your table's small, then you could opt to avoid purging in such cases.
also, rescaling the image to the size you'll display it as is often a good idea (depending on how far you want to take an optimization). assuming the source is larger than the displayed size: this will reduce memory requirements, drawing speed, disk space, and disk read times.
you can also read three20's sources to see what they have done.

Memory leak when application loads in iPhone

I have a navigation based template, when I run my application using Instruments, the very first memory leak comes under:
Leak Object: Malloc 128 bytes
Responsible Library: CoreGraphics
Responsible Frame: open_handle_to_dylib_path
I don't know where this leak is coming from and how remove this.
If it's a default leak, then I think I don't need to worry about it. But if it's not then I have to find a way to remove the leak.
Expanding on deanWombourne perfectly correct answer a bit..
The Leaks Instrument shows you memory that isn't going to be free'd in the normal course of the app (because there aren't any references to it). This in itself is no biggie, it will be free'd when the app exits. A lot of the framework code will allocate and leave these very small chunks of memory allocated. I have no idea if they are mistakes or essential to how the app runs. Whatever, we must accept that they are completely normal.
Leaks will identify these chunks of memory as 'Leaks' and that sounds bad, but this is not really the 'Leaks' that the instrument is there to help you identify.
The 'real' leaks are in the code that can be run many times and which allocate some memory that is never freed, so over time will consume more and more memory until all memory is used and your app will crash.
So if you have an app that no matter how long you use it for or no matter how you use it, it 'leaks' 128 bytes in an apple framework you generally don't have to worry.
However, if you have an app that say, every time you click a button it allocates a new string which is never released - no matter how many bytes the string is - if the user pressed the button enough times this would consume all the memory available to app and eventually crash it. This is the kind of leak you need to watch out for.
The leaks instrument realistically can't tell the difference between the two kinds, but you need to be able to. You might want a kind of singleton object, for example, that there is only ever one instance of, and that needs to exist for the entire lifetime of your app. You create the object on app startup and realistically you never need to free this object, it can be killed when the app exits. Leaks will flag it as a leak, and some other developers that you work with who assume that this means you don't know what you are doing will run to your boss like a little child and say "He's writing really leaky code, and that's reeeeally bad". And your boss, who isn't a programmer will take him seriously because it does sound bad and anyway he scraped a 2.2 in CS from a reputable University so he must know what he's talking about. When really it is completely reasonable and exactly what you meant to do.
So, use the Leaks instrument to find bugs in your code that will ruin your app. Don't worry about every byte found 'Leaking' in an Apple framework.
If it's a one off 128 byte leak then don't worry about it at all, there are better ways to spend your time than thinking about this :)

Will Apple reject my iPhone application because of increasing memory usage?

I have an application with multiple views. It works pretty fine without any leaks or crashes. But when you run using performance tool for leaks, I see when I switch through multiple views and comeback to home screen, my overall size of the application gets increased. Like if its 1.53MB after visiting 4-5 different views and getting back to screen increases the consumption to 1.58MB or less but definitely greater than 1.53MB.
I tried resolving this issue but not able to figure out where I am going wrong since there are no memory leaks.
Does anyone know what could be the problem?
Will apple reject my application on this basis?
I would go back and forth between the screens many many many many times (at least one hundred times). If the memory continues to grow (linearly) during that time, you have a problem. If the memory stabilizes, you might be okay.
Definitely keep trying to fix you memory leaks. But if it's small, I doubt Apple will notice it. I mean, their own apps leak some too. You could get rejected for it, sure. But realistically, leaking a few bytes here and there shouldn't prevent an approval by itself.
(Source, 2 apps approved, one with the same issue, a tiny little memory leak I couldn't track down. I submitted it and was approved. Shortly after, I found and fixed it and released it as part of an update).
If an application has an increasing memory footprint on a known stable state for example named A after going into and coming back from state B which should have no persistent affect on state A and there is no memory leaks this problem called (as much as I know) the lingering memory.
Checklist to be sure if you have lingering memory problem:
App has no memory leaks, or no memory leaks on non-system code when profiled by Instruments.
State A and State B are individually stable states, like in state-machine.
State B has no permanent affect on State A, or it's memory. State A could be a gateway, a menu to another states like State B or State C. But Child states has no or limited info about state A and makes no change about State A.
On loop state changes starts and ends with root state for example A->B->A, A->C->A, A->B->C->A; you encounter increasing memory usage on State A. Memory usage on other child states are not important.
To spot and solve this problem profile your app with instruments. But instead of monitoring leaks, you should monitor allocations and total memory. Every time your app gets to State A, including start, take a memory snapshot. (There is a button for that :D) After snapshot go to State B, State C and use your application as it suppose to. After coming back to root state, in this example State A, take another snapshot. Instruments will show you memory allocations and difference delta in total memory between snapshots. It will also give information about for which object the memory had allocated and when if possible. If it was your code you probably will see the type of class and allocation point. Instruments can not help you about when the object should have been released but when you got the lingering object or memory, figuring out the deallocation point should be much easier.
BUT! Do not forget:
OS and Framework codes could have leaks and lingering memory problems like every OS. If you are sure that it is not your code leaking or lingering in the memory the everything is fine. That was the case in my app and it got approved(App: Tusudoku). System function often use additional memory if there is available, but they immediately release it when received memory warning. Although devices has limited memory, it is a waste if still not used, and using memory does not make memory chip to use measurably increased electrical current. Using memory to the limits for performance and immediately releasing it when someone definitely needs it, is best possible practice. These cache memories does not tend to be grove over time linearly but you should force memory warning every time app gets to root state, in this example State A. So this way you will be sure any cache memory allocated by system or frameworks will be deallocated, then you take the snapshot.
Most of the apps on the App StoreĀ® has memory leaks and other memory problems. The question is how this affect user. Non-linear lingering memory with rapidly dropping acceleration on increase velocity generally won't be a reason for rejection. Calculated the memory usage as 15MB for a perfect working app but if it worked, no problem, say that it will reach 20MB limit max ever and you are good to go. So you later fix your memory problems. Bu if your application has a linear or worse increasing memory usage and can not release that memories when needed, that will be a critical problem.
For more information about memory usage please consider reading official documentation and watching WWDC videos(That's where I learned all about memory fixes using Instruments).
There is no set in stone answer.
On the one hand is the fact that your application may have an obscure memory leak would be enough to reject it according to the posted policies.
On the other hand documents submitted to the FCC by Apple (in the AT&T+Apple vs. Google monopoly fight) give enough detail to work out just how much goes into reviewing an app - unless Apple lied the average app is reviewed by 2 people, and each of them spends around 5 minutes and 38 seconds (assuming Apple doesn't give breaks) to determine if your app passes or fails.
So the answer largely depends on if this memory leak can be discovered in the first 5 minutes of examination by some of the most overworked testers in the industry.
If you are using UIImageViews in your views, then part of the extra memory could be the caching that it does. See here.
Sometimes when we load views, and then switch to another, we leave the view around. For example, if you have a rootviewcontroller that has all the views as retained properties. Normally when you remove a subview, it is released, but not if you have it retained in your viewcontoller. As yu can see, that would add up to memory consumed, but not freed. It's not a leak, except that it gets released only when you release or remove the rootviewcontroller.
You could try to go through and find places where memory is tied up like this, or you could justify it based on the added speed of going through views without having to wait for them to reload.
In summary, it is good to know why your views and other objects consume and hold on to memory, but you may find that all those uses are justified, and you want to keep things that way. Having said that, I don't think Apple will be rejecting our app for decisions like this. If your app crashes because of memory usage, then that would get it rejected.
You're describing very typical memory usage.
If your app runs out of memory and crashes while they're testing it, they will reject it. Beyond that, you're fine.

iPhone Out of Memory WEIRD crashing

My app crashes after about 20 minutes with status 101 (Out of Memory, I believe)
Debugging using Instruments - ObjectAlloc and Leaks gives me no clues. The ObjectAlloc graph stays at a nice constant level of around 1 million bytes (1MB), as does the Net # of allocations. I have got rid of all leaks.
I thought it could be something to do with number of threads, but graphing these in ObjectAlloc also shows them to be constant.
Can anyone point me in the direction of another tool, or another avenue of investigation?
Fix everything Clang finds. LLVM Clang Static Analysis
Remember that objects allocated by the system (and that includes things like images and sounds) don't get tracked in Instruments (although the top level retain counts do, of course). So it's feasable that you're loading images, say, which won't contribute much to your memory usage as show, but can drain a lot of actual memory!
If none of this strikes any chords, you could try the subtractive debugging approach - (take a copy of your project) cut out chunks of functionality until the problem goes away or you get the smallest possible thing that reproduces it. That should at least help you to find where the bottleneck is. Admittedly this will be hard (a) because you'll have to wait 20 minutes or so every time you test (but if you make this a background procedure it's not so bad) and (b) because the nature of memory problems is that there may not be one single cause, but a critical mass of smaller causes.
Good luck!
My experiences with Object Alloc have not been that great. It does not always give you the actual memory used by your application.
Instead, use Object Alloc with Activity Monitor. Make sure you use the "Physical Memory Free" and "Physical Memory used" options in the activity monitor. That will tell you exactly how much memory your application is using.
What do you mean by "nice level". It does not rise over time, at all? How much memory total - it could just be the phone needs some memory for some other app and yours is a little too big to stay up.
The error code 101 means that iPhone OS force quit your app. If you're using UIImageViews in your application, be sure to manage the memory on them. I've found that once my application goes over 10/12 MB, the iPhone terminates it.
If you're not using any image views (or large images), then your backend code is eating up too much space.
All I can say is you need to look at your allocation more carefully and manage what views you keep in memory at any one time.
Run your application in Instruments (Run -> Start with Performamce Tool -> Leaks) to see where your memory is getting allocated.
Hope this helps!

In CocoaTouch (iPhone OS) how do I find/eliminate leaks that the Instruments Leak tool doesn't find?

I have an iPhone app that is running great in the simulator. It responds well to the memory warnings by getting rid of everything that is not absolutely essential. When I run it on the device, it runs well. But after a certain amount of usage it crashes with error code 101 - which, from what I can tell, is the OS killing it due to memory usage. I can see the memory warning (I'm logging it), and my app responds to it, but dies shortly thereafter.
If I look at the app in Instruments (either on the device or in sim), it doesn't find any leaks. In addition, the net memory usage is in the range of 600-700k bytes. Transitioning from the different views of my app increases memory usage (as expected), but when the views and controllers are released and dealloc'd, the memory usage never quite goes as low as it was. However, the addition is usually only something in the range of 1000-2000 bytes. So while Leaks shows me no leaks, I suspect there is an issue somewhere. I've also looked at all of the objects I'm allocating, and all of them seem to be reclaimed as expected. The only objects I see that keep increasing are GeneralBlock-N (where N is some number)
Should I not pay any attention to Instruments net usage figure? What would be the next steps in trying to diagnose the issue?
ADDED: I'm not making any calls to malloc() or any CoreFoundation libraries that would return a buffer that I'm responsible for. The only non-Obj-C calls I'm making are logging statements to NSLog.
One quick thing to try is running the Clang static analyzer. This will find some, but not all, issues in your code that you might be missing. It checks the code at compile time, so it's by no means infallible, but will almost certainly find most glaring problems.
You should also run your application with the memory monitor instruments to see overall system usage on the device.
Leaks only finds memory that is not referenced by anything, but still retained.
What you are seeing is that you have left memory retained, and still referenced by something.
One thing to look for especially, is that if you have passed a reference of a class to something else as a delegate that you free it in your dealloc method.
Similarly, if you have subscribed to any notifications you should unsubscribe in viewWillDisappear: (if you use the general unsubscription method in a view controller do not forget to re-subscribe to the memory warning notification.
Timers are the same way, deactivate them when a view goes away and re-enable them when the view comes back (unless of course you need a timer running the whole time your application is running).
Basically be suspicious of anything you give a reference of a class to, and try to figure out how you might eliminate that link whenever possible (either in dealloc or viewWillDisappear: or both).
Here's a summary of what I've learned (thanks to some excellent answers and comments):
Object Allocation is NOT the same as Memory usage. The answer to my question about ObjectAlloc's net bytes element is that you shouldn't be paying attention to it - at least not when determining issues with the amount of memory you are using or whats causing it to crash. It doesn't reflect the true memory usage of your application.
My amatuerish guess is that ObjectAlloc only shows you the memory taken up by the direct object itself. So if you have an UIImageView, it takes up just a handful of bytes to store the various properties, but it might be pointing to an image in memory taking up a bunch of space. Therefore, looking at ObjectAlloc is helpful only in making sure you're not creating and keeping objects around, it won't give you an idea of how much memory you're using or how much you can use before crashing.
MemoryMonitor will give you the total memory usage. You can constrain it to viewing only your app's usage by using the search tool in the bottom right of the Instruments window.
Both ObjectAlloc and Memory Monitor (as well as the Leaks tool) are plugins for Instruments - just in case thats not obvious to someone else. You can launch Instruments from within XCode by doing Run -> Start with Performance Tool. Once inside of Instruments, you can open the Library and add new plugins to monitor different aspects of performance.
One thing to look for is circular references.
(I don't want this to sound patronising - just want to make sure I'm being clear:) If object a refers to object b and object b refers to object a, there may not be a reported "leak" because all the memory is still referenced - but this may be an orphaned island of objects, seperated from your app and never reclaimable. Of course it may involve more objects ( a refers to b, b refers to c, c refers to a, etc).
If you're building up a graph of objects somewhere, and there are any back or cross references, be sure to break the circles if you release the root (there are different ways of doing this. The simplest is probably to make sure each class in question has a releaseAll method, or similar - which calls releaseAll on it's child objects, then releases the child objects - but this isn't always the best solution).