I'm trying to optimize the memory usage of an iOS app, and I'd like to see what the app's total memory usage is at specific points in the code. I was thinking I should be able to set breakpoints, profile the app with Activity Monitor, and just look at the memory use when each breakpoint catches. But when I run Instruments, it seems breakpoints no longer stop execution, so it's hard to know exactly when memory usage is changing.
Is it possible to use breakpoints and Instruments at the same time? If not, is there a clever way of writing some code to insert a marker into the Instruments timeline when specific events occur?
I also ran into this issue today, and after a bit of searching I found this solution. Text below is a quote from the post:
Breakpoints Do Not Break. Instruments utilizes debug information from
your debug build, however, it does not stop at break points you set.
This is because while you are loading your application into
Instruments from the menu in XCode, Instruments simply uses the path
of the current executable as its start path and loads it externally
from XCode. The menu in XCode is really there as a convenience
mechanism. This is not a big deal as you can always run again in Debug
mode after your instruments session should you want your application
to break. It’s just something to make a note of.
NSLog Statements Do Not Show In The Debugger Console. If you want to
see your NSLog statements, you will need to load the system Console
application (/Applications/Utilities/Console).
Reference: http://www.cimgf.com/2008/04/02/cocoa-tutorial-fixing-memory-leaks-with-instruments/
Well, you aren't running under control of the debugger.
One approach might be to add alerts at the key points, and take a heapshot then (manually).
Or there may be some dtrace wizardry.
Related
My app seems to have a memory problem. I'm not getting any crashing, but when testing on device, both Instruments and the Debug Navigator agree that the amount of memory my app is using keeps increasing depending on what I'm doing in the app.
So, I tried to diagnose the problem.
First, I thought about normal memory leaks -- and there were many. So, after a lot of work with the Instruments -> Leaks template, I was able to eliminate them.
But the memory problem persisted.
So, I decided to look for zombie objects. First, I enabled zombies in Xcode. Because I was unsure whether I needed to enable zombies for "Run" or "Test" or both, I did both. So, that's Edit Scheme -> Run -> Diagnostics -> Zombie Objects and Edit Scheme -> Test -> Diagnostics -> Zombie Objects.
I was also unsure whether to run Instruments through a debug or release build configuration, so I tried it with both (with the same outcome).
Here's a screenshot showing the location of the Debug Navigator:
Here's a screenshot of the memory options I enabled prior to using View Memory Graph Hierarchy:
Now that zombies are enabled, I go to Debug Navigator -> View Memory Graph Hierarchy, and Xcode builds a memory graph that says my app has something like a thousand zombie objects. There are zombies of all kinds -- everything from SceneKit stuff to CloudKit and GameplayKit stuff.
Here's a screenshot of some of those zombie objects:
So, I decided to investigate further using Instruments.
Here's what Apple says on using Instruments to detect zombies:
"If a call is made to a deallocated object, a flag is inserted in the
timeline pane and a Zombie Messaged dialog appears, indicating that a
message was sent to a deallocated object at a specific memory
address."
However, if I open Instruments and use the Zombies template, I never see any such flags/dialogs.
Here's a screenshot showing what I see after running the Instruments Zombies template (notice the lack of flags/dialogs):
Question: Why might the memory graph hierarchy tool and Instruments disagree so markedly on the presence of zombies? Is there some further Xcode configuration I'm missing or something? How should I proceed?
Thanks!
While profiling an app (which has metal codes for gpu acceleration) Time Profiler Instrument gives the error as in the screenshot:
It says, No configuration information received.
I want to know what kind of configuration is missing and how to configure it. I have also observed that other instruments: Allocations, Leaks, VM Tracker has no issues.
I would make sure OSX, XCode and the device's iOS are all fully up to date and power cycle everything. If that doesn't fix it, I'd temporarily modify the app's deployment target to the highest possible option.
If that doesn't fix it check to see if it happens using the metal demo (XCode->File->New->Project->iOS Game Metal) then look to file a bug with Apple: https://feedbackassistant.apple.com/
Xcode 5.1 no longer officially supports GDB, instead defaulting only to LLDB. The problem with LLDB is that it shows no useful debug information on app crashes. Furthermore, all Exception Breakpoints simply break on main.m. This makes debugging ridiculously tedious. I read here on SO that this is a common problem with LLDB and that GDB does a better job.
How do I enable GDB for xcode 5.1?
There is no way to use gdb with more recent Xcodes.
I don't know what you mean by "it shows no useful debug information on app crashes." Probably best to file a bug with bugreporter.apple.com with some more detail, there may be a way to get lldb to work correctly for you.
I am also not sure what you are seeing when you say "all Exception Breakpoints break on main.m". If you go to the lldb console and do:
(lldb) break list
are the breakpoints actually on main.m?
One thing to be a little careful about with the Xcode 5 Debugging UI (maybe this started with 4, I can't remember.) When your program stops due to a crash or exception in a stack frame that starts with frames that have no debug information, Xcode will actually select the first frame up the stack that has debug information. This is to avoid showing people screens full of disassembly, which some folks find frightening... So the source frame will show, say, main.m, though the actual bottom-most frame is something else.
Xcode also has a "stack compression" feature that will hide "uninteresting" frames. That can also make this kind of stop confusing - though it will generally show the bottom-most frame you might miss that and only see your source frame. The stack compression can be turned off if you don't like it.
Make sure that is not what you are seeing.
I've been running into a problem with Apple Instruments (4.6, Xcode 4.6.2 on 10.8.3).
Normally when using the Time Profiler, I can look at my source and see the hotspots without any problems (same project).
This time I've been trying to use the "Counters" Template to sample my CPUs Performance Counter Events. It samples the events as it should and I also have the same time based profiling information as well, however when I try to step into my code to look at the hot spots, like I can do for the "Time Profiler", all I get is "Unavailable" where I used to have the source. No Assembly either.
The Project is built as:
Release build
Debugging information is on and not stripped
DWARF + dsym is used to store the profiling data.
As I said, its the same configuration that works for the time profiler.
I already tried to (pretty much all that's stated in here: Xcode 4 Instruments doesn't show source lines , except for doing -O0, debug performance is not of interest to me)
recompile
relocate the dysm file using "File -> Re-Symbolicate"
As soon as I plainly close Instruments, start another Profile from Xcode and choose the Time Profiler, it works, if I go back to the Performance Counters, it stops.
Is this the default behaviour? Should it be like this? Has anybody already managed to get it working, in the current Instruments version? Otherwise it might be worth to file a bug with Apple.
Thanks a lot!
Try the Xcode 5.1 beta4. For me its fixed there: Counter works now.
The seed notes mentions some details what they did. Don't know if its under NDA.
I have a huge synchronization process in which I download and unzip 400-500 XML files and then parse it. With this data Im going to create a lot of core data objects over the RestKit API. At the beginning, I had a memory warning with live bytes of 450mb+ because I did not using autorelease pools and only tried to save core data on the end.
I fixed that, saving now frequently to core data and using #autoreleasepool blocks. When im running my app now with instruments, I can see how the live bytes only being 20mb-30mb, always releasing memory and never going to size up. The process just works. But when I start the app without instruments, after a view files I get a Memory Warning. Later on the app crashs.
What is the differene between running the app with and without the instruments tool? Why does it end in different results?
I'm adding this answer because I'm so happy that I came across this page.
What #borrrden suggested is partially true. You can configure which Build settings it will use when you profile. To configure this, goto Xcode and open the Edit Scheme dialog and select in the left menu Profile XXX.app. You will see you can choose a Build Configuration (either Debug or Release).
What #hooleyhoop commented was more crucial to find the solution. Even if your Profile Build Configuration is set to Debug, there is still a difference between Profiling and a default Run from within Xcode. You can specify Diagnostics in the Run section. Right there, there is an option called Enable Zombie Objects under Memory Management. Make sure that this option is unchecked.
These diagnostic Run settings are not used while profiling. That is the explanation for the behavior you are experiencing. There isn't a Diagnostics tab on the Profile section as well.
The result is that my game (Gump) crashed after 5 minutes of doing nothing in the main menu with Zombie Objects enabled. Once I disabled Zombie Objects, my game runs as far as I know for an infinite amount of time. After 45 minutes, still no Memory Warnings.