Getting Low Memory Logs/Reports on iOS Programmatically - ios

I am currently using PLCrashReporter to get the crash reports on ios device programmatically. According to https://developer.apple.com/library/ios/technotes/tn2151/_index.html , http://www.raywenderlich.com/23704/demystifying-ios-application-crash-logs Memory logs are different than crash logs. How can I get this memory logs programmatically ? Are there any libraries available ?

You need to use Instruments to determine why the memory is being exhausted. Use the Analyzer to check your code. Use Instruments Leaks tool.
Use instruments to check for leaks and memory loss due to retained but not leaked memory. The latter is unused memory that is still pointed to. Use Mark Generation (Heapshot) in the Allocations instrument on Instruments.
For HowTo use Heapshot to find memory creap, see: bbum blog
Basically the method is to run Instruments allocate tool, take a heapshot, run an iteration of your code and take another heapshot repeating 3 or 4 times. This will indicate memory that is allocated and not released during the iterations.
To figure out the results disclose to see the individual allocations.
If you need to see where retains, releases and autoreleases occur for an object use instruments:
Run in instruments, in Allocations set "Record reference counts" on (For Xcode 5 and lower you have to stop recording to set the option). Cause the app to run, stop recording, drill down and you will be able to see where all retains, releases and autoreleases occurred.

One way is to plug in the device to Xcode. Go to Window > Devices and Simulators, select your device, click "View Device logs" button. Low memory logs will be in there under process "Unknown" and type "Unknown".
See https://developer.apple.com/library/content/qa/qa1747/_index.html under "Getting Crash Logs and Console Output From a Device Using Xcode" section.

Related

How to debug memory leaks when Leaks instrument does not show them?

I have an iOS app written in Swift that is leaking memory - in certain situation some objects should be released but they are not. I have learnt about the issue by simply adding deinit debug messages like this:
deinit {
println("DEINIT: KeysProvider released")
}
So, the deinit message should be present in console after such events that should cause the object to release. However, for some of the objects that should be released, the message is missing. Still, Leaks Developer Tool does not show any leaks. How do I solve such situation?
In Xcode 8, you can click on the "Debug Memory Graph" button, in the debug toolbar (shown at the bottom of the screen):
See Appleā€™s Diagnosing and Resolving Bugs in Your Running App: Visualize and Diagnose Increasing Memory Usage.
Just identify the object in the left panel that you think should have been deallocated, and it will show you the object graph (shown in the main canvas, above). This is very useful in quickly identifying where the strong references were established on the object in question. From here, you can start your research, diagnosing why those strong references were not resolved (e.g. if the object in question has a strong reference from something else that should have been deallocated, look at that object's graph, too, and you may find the issue (e.g. strong reference cycles, repeating timers, etc.).
Notice, that in the right panel, I'm seeing the call tree. I got that by turning on the "malloc stack" logging option in the scheme settings:
Anyway, having done that, one can then click on the arrow next to the relevant method call shown in the stack trace in the right panel of the first screen snapshot above, and you can see where that strong reference was originally established:
The traditional Instruments technique (especially useful if using older versions of Xcode) is described below, in my original answer.
I would suggest using Instruments' "Allocations" tool with the "Record Reference Counts" feature:
You can then run the app in Instruments and then search for your class that you know is leaking and drill in by clicking on the arrow:
You can then drill into the details and look at the stack trace using the "Extended Details" panel on the right:
In that "Extended Details" panel, focus on your code in black rather than the system calls in gray. Anyway, from the "Extended Details" panel, you can then drill into your source code, right in Instruments::
For more information and demonstrations in using Instruments to track down memory problems, please refer to:
WWDC 2021 video Detect and diagnose memory issues
WWDC 2019 video Getting Started with Instruments
WWDC 2018 video iOS Memory Deep Dive
WWDC 2013 video Fixing Memory Issues
WWDC 2012 video iOS App Performance: Memory
Use instruments to check for leaks and memory loss due to retained but not leaked memory. The latter is unused memory that is still pointed to. Use Mark Generation (Heapshot) in the Allocations instrument on Instruments.
For HowTo use Heapshot to find memory creap, see: bbum blog
Basically the method is to run Instruments allocate tool, take a heapshot, run an iteration of your code and take another heapshot repeating 3 or 4 times. This will indicate memory that is allocated and not released during the iterations.
To figure out the results disclose to see the individual allocations.
If you need to see where retains, releases and autoreleases occur for an object use instruments:
Run in instruments, in Allocations set "Record reference counts" on (For Xcode 5 and lower you have to stop recording to set the option). Cause the app to run, stop recording, drill down and you will be able to see where all retains, releases and autoreleases occurred.

Where can I find the Memory Monitor Instrument on the Mac?

I am having a hard time debugging memory crashed on an GPU-intensive app.
This answer talks about the Memory Monitor Instrument:
https://stackoverflow.com/a/10951144/1167349
So does this docu page from Apple:
https://developer.apple.com/library/ios/documentation/AnalysisTools/Reference/Instruments_User_Reference/MemoryMonitorInstrument/MemoryMonitorInstrument.html
However, when I open up Instruments, there is no Memory Monitor to select:
(yes, I also used the scroll bar)
When I open up the Library, I can not find it there, either. Although the "VM Tracker" and "Shared Memory" instruments have the same icon, they do not provide the same functionality:
Am I missing something really obvious here??
I am using XCode Version 6.1.1 and Instruments Version 6.1.
Thank you a lot for all answers!
Select the Activity Monitor template. Older versions of Instruments had separate monitoring instruments for activity, memory, network usage, and file usage. In Xcode 6 Apple combined these monitoring instruments into one Activity Monitor instrument that you can configure to show the data you are interested in, which is memory usage in your case.
The Activity Monitor instrument is not initially set to graph memory usage. You will have to go to the Record Settings section of the detail view on the right side of the trace window and tell the instrument to graph and list memory usage.

Out of memory in XCode, but not in Instruments

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.

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

Why do allocations continue to rise in Zombie Instruments tool when they don't in Allocations Instruments tool

I'm new to Xcode and iOS and have been experimenting today with the Instruments tool. There are some things I'm struggling to get my head around:
Scenario:
I have created a simple app that filters a UITableView with a UISearchBar (target iOS5 with ARC). Simple code, nothing too fancy.
For my own learning, I was watching the allocations as I perform various actions - in this particular instance when I'm typing in the search bar.
Using the 'Allocations' instrument tool, I get the following:
As expected, I see a sudden spike in memory allocated when I first start typing in the search bar. After that, any further searching makes no significant difference to the allocation graph.
However, when I look at the memory allocations using the 'Zombie' instrument tool, the allocation graph continues to rise whenever I type in the search bar.
At first, I thought this may have been to what I was tracking - and I tried to ensure all the settings were matched. However, it still shows a rising graph when searching.
Does anyone have an explanation of this? No doubt I have some conceptual misunderstanding about what the allocation tool is tracking in each of these instrument modes.
The Zombies instrument works by telling your app not to free objects. Instead, when the object would be deallocated, the app instead leaves the object allocated but changes the object's class to a special zombie class that handles any message by raising a zombie error.
Thus, allocations keep rising under the Zombie instrument because nothing is really deallocated.
Incidentally, since using Zombies prevents the app from deallocating objects, the app usually requires much more memory to run under the Zombies instrument. This is ok on a Mac (and in the iOS Simulator running on a Mac), since the Mac probably has several gigabytes of RAM and also supports paging to disk. But iOS devices only have between 256 MB and 1 GB of RAM, and don't support paging. This is probably why Instruments won't let you use Zombies on an iOS device.

Resources