Out of memory in XCode, but not in Instruments - ios

My app is running out of memory. In XCode's memory report I can see the memory usage rise on the device to a little bit above 500Mb before it is shut down.
When profiled in Instruments (either with the allocations tool or the leaks tool) this does not happen. The process runs up to about 100Mb and balances out as it runs the memory intense portion of the task. The app does not crash when run in Instruments.
What would cause the discrepancy?
The intense process that runs is utilizing a UIWebView to determine the length of a number of pages of content. The web view is in the background and loads a page. On completion of the load it calculates the size and loads the next page until all pages have their length calculated.
Since I have been unable to get the same memory issues to occur in Instruments, I added logging to init and dealloc methods on all of the major parts and can confirm those are being allocated and released as expected.
After that, I tried assuming that allocation and deallocation was happening properly, but that I was just allocating faster than the system could reallocate memory. I tried stopping the process early before memory ran out to see if the memory usage would drop. XCode's memory report does report a small drop, but not by a significant amount -- even after letting it sit for a few minutes.
My next step is to try to simplify the process until the problem is eliminated.
Has anyone else come across something like this where an app in Instruments does something completely different than not in Instruments or have any explanation for what might cause that?

I would look at the two schemes and make sure the settings are the same. It's possible that the profiler is using a non-debug configuration and "Run" is using debug configuration.
I'd pay special attention to the "Enable Zombie Objects" in the "Diagnostics" tab of the "Run" configuration, as that can take up memory keeping track of all of the deallocated objects. Zombies are a wonderful diagnostic tool, but you want to turn that off in order to ensure you reclaim all of the memory associated with the deallocated objects.
For information on getting to the scheme configuration, see https://developer.apple.com/library/mac/recipes/xcode_help-scheme_editor/Articles/SchemeDialog.html.

Related

Using instruments to find memory leaks

I've tried to read almost every decent tutorial in the internet, but still can't understand what is really happening here:
I've "Hide System Libraries" and "Invert the call tree", but I do not understand how to find actual code responsible for for example this leak. Any tips are appreciated. May be I am missing something obvious. I am getting hundreds of leaks, however I am using weak in closures, I do not have classes referencing each other etc. But it looks like I am missing something fundamental.
The problem shown in your screenshot is Instruments can't find your app's debug symbols. Instruments is showing memory addresses instead of function names. You are not going to be able to find the source of your memory leaks in Instruments without function names, even if you invert the call tree and hide system libraries.
Make sure your project is generating debug symbols. Check that the Generate Debug Symbols build setting is set to Yes. If your project is generating debug symbols, Instruments may be unable to find the dSYM file that contains the debug symbols. In Instruments choose Instrument > Call Tree > Locate dSYM. The dSYM is usually in the same directory as the release version's application bundle. The following article has additional information:
Instruments: Locating dSYM Files
Memory leaks can be difficult to track down. This is likely going to be a time consuming process, so be prepared. In the end, there is usually a lot of trial and error with debugging memory leaks. The "Memory Leaks" instrument has actually only detected one leak for me in the past. I've always had to track them down myself using the "Allocations" instrument.
One of the things that has helped me in the past is to start by trying to figure out what objects are actually being leaked. Click on the allocations instrument (the row above "Leak Checks"). Now try sorting by number of objects released or amount of memory used. See if there are any objects that have a count of 0 released when they shouldn't be sticking around. See if there is an object type that is taking an abnormal amount of memory.
Memory leaks are always due to developer mistakes with memory management. There are some minor memory leaks that exist in some of the lower level private APIs in Foundation and UIKit. At those lower levels, they are dealing with a lot more manual memory management, so its much easier to make tiny mistakes. You can't really do anything about those, but they are relatively rare.
If your application is working just fine, you may not need to worry about fixing these. There is some cost benefit analysis you want to do here. If this isn't impacting performance or stability, is the time investment in fixing these right now worth the minor benefits it will provide you and your users?
However it is worth nothing that memory leaks can add up, so if a user has your app open for a long time, the amount of leaked memory will eventually become a problem if you continue to leak more objects over time. At some point the application will crash and the user will have to re-open. But if your memory leaks are small enough that this doesn't become an issue unless the app has been open for HOURS, is it really that much of a problem anyways? That's always a judgment call on your part.

app works fine on iPad 2, crashes on iPad 3, with low memory warning

as the title says, I have an app which works on iPad 2, but crashes on iPad 3. when running it the console gives me a low memory warning message. When the crash happens I symbolicate it, but there's really nothing that I can relate to the code, like it shows
process name, UUID, rpages, recent_max, [reason] (state)
and under those column headers just hexadecimal stuff, nothing showing method calls or lines in the project.
Any ideas? am I missing some flags in the code that allows for a better crash log?
Thanks.
If you're getting low memory warnings and fail to release enough memory to resolve the issue, your app will almost certainly crash. The thing is, I don't think that the particulars of how or why it crashed can possibly be illuminating. At that point, you're evaluating secondary symptoms. You really need to go back and figure out why you got the low memory warning in the first place and fix that problem.
As Daniel said, you can look at Technical Note 2151, but as it says:
When you see a low memory crash, rather than be concerned about what part of your code was executing at the time of termination, you should investigate your memory usage patterns and your responses to low memory warnings. Memory Allocations Help lists detailed steps on how to use the Leaks Instrument to discover memory leaks, and how to use the Allocations Instrument's Mark Heap feature to avoid abandoned memory. Memory Usage Performance Guidelines discusses the proper ways to respond to low-memory notifications as well as many tips for using memory effectively. It is also recommended that you check out the WWDC 2010 session, Advanced Memory Analysis with Instruments.
So, a couple of thoughts:
Have you looked for leaks? The Finding Leaks article walks you through how to use instruments to find your leaks.
If you turned on zombies, have you turned them off? Zombies is a great diagnostic tool, but just consumes memory.
Have you run your code through the static analyzer (shift+command+B or select "Analyze" on the "Product" menu)? Especially if using non-ARC code, this can find lots of memory issues.
Have you examined your allocations for unexplained increases without offsetting decreases with the Instrument's Allocations tool. Using that, you can run the program, look at the consumption of memory on the graph and see if you see any increases that aren't offset at some point by the corresponding decreases. And if so, highlight those increases in the graph:
For example, when running the Allocations tool, hold down the option key and then click-and-drag with your mouse to highlight a portion of the timeline, to identify what you want to inspect. You probably want to focus on one of your spikes in allocations. For example, I found a bump in my allocations and highlighted it as such (this was a ludicrously simple example where I create a huge array in viewDidLoad, but hopefully it give you the idea):
Note, I find it useful to show the call tree in the lower panel, it's often useful to select "Hide System Libraries", to focus on your code (and "Invert Call Tree", too). And if you double click on the method name in Instruments (in my example, here, it would be viewDidLoad), Instruments will then show you your code that's doing the allocation:
Low memory warnings generate a different kind of log than standard crashes. Take a look at the "Understanding Low Memory Reports" section of this article to understand what happened with your application and how you can debug it using Instruments: http://developer.apple.com/library/ios/#technotes/tn2151/_index.html

iOS -- Using and Understanding Instruments using Allocations and Memory Monitor (Physical Memory Free)

I'm in the process of understanding how to put instruments to better use. I just finished a leak management exercise, and instruments is reporting very few leaks. I'll figure those out later. In the mean time, my app is crashing, and it appears that its related to memory pressure.
So I looked at this in Instruments. I have Allocations and Memory Monitor in use. Allocations shows a pretty steady 3 to 4 MB Live bytes while I just let my app initialize and come to equilibrium. Overall bytes, however, jumps to over 50 MB. I didn't think much of this until I looked at the Memory Monitor and I see that memory usage goes up and down, causing memory warnings. (It seems strange to me that this doesn't show up on the allocations graph at the same time.)
The app should be at an equilibrium point, but apparently it's not. My question is how can I use instruments to help me understand why memory usages is rising and falling?
Instruments as a tool for debugging is simply excellent. From what I can understand, you have been trying to use the allocations tool, so I'll go over that. Allocations details the number of objects your application allocates during it's execution, along with their in-memory references, locations, even the calling code that allocates said objects. When instruments starts running the allocations tool, your application begins reporting all allocations as blue dots, which pile up higher and higher as your application executes (naturally, as you should be allocating more and more objects). Overall Bytes displays the amount of memory EVERY allocation your app has made added together. I want to stress this for your case: it does not mean your app is currently using 50 mb of memory!, it just means that your app has used 50 mb total. Your app is obviously limited to the amount of memory the device has, and 3-4 mb is not a lot when you consider that the first gen. iPhone had about 128mb, but for more complicated applications, the OS will usually kill off other applications before it kills yours.
As for the other allocation graph with spikes, rather than a continuous line graph, that is to detail the number of allocations going on at that point in time. Usually, the spikes can be ignored, unless there are a lot of large spikes in one small amount of time.
Anyways, to address your specific memory warning problem, it honestly depends how many memory warnings you are receiving, and at what level the warning are at. And as for your leaks, my only word of advice is: Squash them as soon as possible! When you see a leak (a red bar in the leaks tool), click on the bar and find the objects that are being leaked. When you select a leaked object, then select the right sidebar, it will show you the code that is leaking. When you double click on any part of the right sidebar, it'll even open up the specific line and class the leak originated from!

iPhone memory warnings and crashes - but Instruments showing lowish memory use

I have a strange memory issue I'm having problems resolving and would appreciate some advice as to where else to look.
The program I have (iPhone App) has a function whereby it basically downloads loads of files, processes those that are JSON, and stores the rest to disk. The JSON processing is CPU intensive and can take several seconds per file, so I have a NSOperationQueue with maxConcurrency limited to 1 that handles all the heavy lifting, and a queue that manages the multiple files to download.
Ever since iOS5 came out, the App has had problems completing the download sequence without crashing and so far what I have tried is;
1) Changed the performSelectorOnBackgroundThread JSON processing to use a single NSOperationQueue so as to limit the number of background threads working with large objects.
2) Added NSAutoReleasePools inside loops that create multiple, large, transient objects.
3) Flushed the sharedURLCache to ensure the files aren't hanging around in the system cache.
4) Stored the JSON objects to disk using NSKeyedArchiver and passed the filenames between threads rather than the actual objects, to again try to mitigate the number and size of retained objects currently in use.
All of these at first seemed to make a difference, and when I look at the memory allocations, I've now got the peak usage down from just over 20MB (hence no wonder it was crashing) to under 10MB, and yet the app is still crashing with low memory as before.
I'm trying to trace what is eating the memory causing the app to crash and on this occasion I'm having real problems persuading Instruments to tell me anything useful.
Here's a typical trace (on an iPhone 3GS running iOS 4.3.5)
You can see that the PEAK usage was a tad over 7MB and yet shortly after, you can see the 2 flags pertaining to low memory, and then low memory urgent, followed by the app terminating shortly thereafter.
If I use the memory monitor, the cause of the crash seems clear enough - physical memory is being exhausted - look at the light green trace below. The low memory warnings co-incide (not surprisingly) with the physical memory running out.
There are no leaks showing FWIW either (I've done that in other runs).
It's not image caches or NSURLConnection caches and the only thing I can think of is that perhaps there are some bad leaks that aren't being detected ... but I'm having issues identifying them because if I click into all allocations to see the objects that are live, and then do a command-A to select them all (in order to paste them into a spreadsheet to see where the memory seems to be), at the point I hit command-C to copy them, Instruments beachballs and never recovers.
I really cant figure out what's going on. Does anyone have some advice on how to persuade instruments to show me some more useful information about what is using this memory?
Sorry I can't post any meaningful code fragments ... hopefully the instruments screenshots at least give you an idea about where I'm coming from.
The Leaks instrument isn't terribly useful for figuring out anything but the obvious leaks in your app.
What you are describing is an ideal candidate for heapshot analysis.
tl;dr Heapshot analysis allows you to see exactly how the heap of your application grows between any two points of time (where you determine the points).

Ambiguities in using Instruments for iOS Development

I am Profiling an Application with Instruments. The profiling is done using Allocations Tool in two ways:
By choosing Directly the Allocations when I run the App for Profiling
By Choosing Leaks when I run the App for Profiling.
In both the cases , I had Allocations tool enabled for testing. But surprisingly , I had two different kind of Out put for Allocations at these instances.
Are they supposed to behave differently? or this is a problem with Instruments.
The time I Profile the with Leaks Tool:
In Allocations Graph:
1. I get lot of Peaks in Graph, The Live bytes and overall bytes are same.
2. I get the Black flags (I think it alarms about memory warning) after 1 minutes usage. Then after a set of flags appearing, my App Crashes. (This happens at times, even when directly run the App in Device)
The time I Profile the with Allocation Tool:
In Allocations Graph:
1. I do not get peaks often as it was in the above case. The Live bytes was always way less than Overall bytes.
2. I have used for over 20 minutes and never got Black flags.
One fact I came to know is that, when Live bytes and overall bytes are equal, the NSZombieEnabled could be enabled.
Have any of you ever encountered this problem.
UPDATE 1:
I faced another problem with first case. Whenever I profiled after a short duration (compared to profiling in second case), the app got lots of Black Flags and my App Crashed. (Due to Memory warning)
And when I tried the similar step by step use of Application my Application did not crash and got no flags.
Why this discrepancy?
In the first case, you are only tracking live allocations because the "Leaks" template configures the Allocations instrument that way. In the second, you are tracking both live and deallocated allocations. (As CocoaFu said).
Both are useful, but for slightly different reasons.
Only tracking live allocations (in combination with Heapshot Analysis, typically), is a great way to analyze permanent heap growth in your application. Once you know what is sticking around forever, you can figure out why and see if there are ways to optimize it away.
Tracking all allocations, alive and dead, is a very effective means of tracking allocation bandwidth. You can sort by overall bytes and start with the largest #. Have a look at all the points of allocation (click the little arrow next to the label in the Category of the selected row), and see where all the allocations are coming from.
For example, your graph shows that there are 1.27MB of 14 byte allocations -- 9218 allocations -- over that period of time. All have been free()d [good!], but that still represents a bunch of work to allocate, fill with data (presumably), and free each one of those. It may be a problem, maybe not.
(To put this in perspective, I used this technique to optimize an application. By merely focusing on reducing the # of transient -- short lived -- allocations, I was able to make the primary algorithms of the application 5x faster and reduce memory use by 85%. Turns out the app was copying strings many, many, times.)
Not sure why your app crashed as you described. Since it is a memory warning, you should see what is most frequently allocated.
Keep in mind that if you have zombie detection enabled, that takes a lot of additional memory.
Depending on the way Allocations is instantiated there are different options. Check the options by clicking the "i" symbol in the Allocations tile.
Yes, I find this annoying also.

Resources