Profiling in XCode 4


#1

Just thought I’d ask and see if any of you guys had any tips for someone whose just about to profile his code for the first time, trying to find the parts of my code that need to be optimized. Im working in XCode 4, and would like to reduce certain parts of my program that seem to eat up more CPU than they should, probably having to do with drawing and whatnot… I guess I’m just not sure exactly where to start (but I have managed to figure out how to run XCode 4 to Profile/Analyze and to select various tools it has like Leaks, Allocations, etc)…Even pointing to other useful online resources would be great help.

Cheers!


#2

After reading through Apples documentation I tried out Shark this evening. I’m not sure where the bottle-neck is (or if there is any useful information there that I don’t understand). I don’t really see any of my function calls and whatnot near the top as hot-spots, but I suspected that the bottleneck has to do with painting, although Im starting to doubt that. I don’t do anything fancy, just make use of quite a bit of lines (g.drawVerticalLine), and rects/rounded rectangles (g.fillRoundedRectangle).

When I start my app, it idles aroun 5% CPU in Activity Monitor, not too bad. Adding an Audio Recorder object jumps the CPU up to around 15%, even if I am not painting the wavform display. Adding other kinds of recorder objects has similar cpu hits, adding about 10% cpu usage per item. I commented out any of the fills and shapes on the objects and they still have about 10% cpu hits per item. As you can imagine, im often in the scenario where I need to record using at least 5-10 of my objects, so that easily puts me in the 50%-90% CPU usage range, and although the app runs, certain things can start to feel sluggish (e.g. dragging recorder objects around and repositioning them on screen).

Any tips? Ill keep playing around with Instruments and Shark… thanks

Heres a screenshot of shark output - http://dl.dropbox.com/u/11427810/Screen%20shot%202011-08-12%20at%206.54.03%20PM.png
and one of my app’s gui - http://dl.dropbox.com/u/11427810/Screen%20shot%202011-08-12%20at%206.58.17%20PM.png


#3

Shark might be a bit heavy weight for what you need(its good for looking at the assembly though).

Instruments and sampler, (I’ve only spent some time in Xcode 4, and I don’t recall it in the template page, only Activity Monitor, so create a blank “instrument” and drag Sampler from the library list.

Then like Shark you run your app, although you get a timeline which you can isolate sections of(to get past all the boot/setup stuff). Then view just the main thread(as that’s where your drawing (should!) be happening. Then you’ll see the heavy calls which you can then disclose to see your bottlenecks. Or you still just view the main thread, Toggle off invert call tree and option click the disclosure triangle(to open all sub tree’s) on Main Thread. Scroll down to where the library name changes from your app name to something else(it’s also where the % tends to change, ie it’ll be 15% all the way down and then things start to split off. When this number changes dramatically tends to be the issue) and this will give you an idea of your heaviest areas.

Just a few tips, hope that helps!


#4

Thanks Justin, that actually helped quite a bit! I was confused as to what the instruments library was… My mistake for thinking the template window in xcode4 was all inclusive! Anyway, I think I’ve followed it to that big %jump, at Mach_msg (as per the screen shot attached). Does this mean anything to you? Thanks again, J

http://dl.dropbox.com/u/11427810/Screen%20shot%202011-08-13%20at%201.01.20%20AM.png


#5

Almost, can you scroll down a little more? You are at the top of the juce drawRect function, if there is a bottleneck in JUCE performance you’ll see it where the now 13% changes


#6

That mach_msg that’s gobbling up 79% is strange though! I don’t have that in any of my traces… if you uncheck hide missing symbols does it tell you anything more? (Actually don’t worry, I don’t see it as i’m building with 10.4 deployment so it’s probably a difference between CFRunLoopGetCurrent and CFRunLoopGetMain(in osx_MEssageQueue.h)


#7

hmm, heres scrolling down a bit more…
http://dl.dropbox.com/u/11427810/Screen%20shot%202011-08-13%20at%201.23.01%20AM.png

I tried unchecking Hide Missing Symbols but doesn’t seem to give any more insight, at least that I can see…hmm


#8

Doesn’t look like your performance issues are with JUCE’s graphics / drawing (well based on this sampling, which on closer look, looks to be for the entire duration of the sample). You say it feels sluggish when you drag things around, so watch the timer increment and note the position when you start dragging around objects for awhile. Then swap to instruments, pause execution, click back to that position click on the left inspection range button and then go to just before the activity in the lane starts to die down again and click the end selection range, does this sample help?


#9

I get the mach_msg_trap when my app is sitting idle(I looked at CFRunLoop sources and its what keeps the app tickling for events.) So I think key is what I suggested above, do something busy, pause the app’s execution in instruments and mark the in/out points to that area that felt sluggish. Fun stuff huh?


#10

:slight_smile: Definitely! I’m glad I’m finally digging into this though because its an important skill. I’m going to call it an evening for now (its 2am in New Zealand) as its been a pretty full-on day but will definitely dive back in tomorrow and report back. Thanks again for all your insight, I really do appreciate it.

All the best,
J


#11

If you still want to have a look at the graphics CPU usage, there is a really fabulous juce flag for paint optimization …

#define JUCE_ENABLE_REPAINT_DEBUGGING 1

set that in your AppConfig and you will see that Juce paints a little color difference over every section as it paints … letting you see how much painting is going on where. Very useful for graphics optimization.


#12

Awesome, I have gotten things going a bit better. Each of my Recorder objects were repainting (the entire component) on a timer at 1/50 of a second. This was to redraw a filled rectangle which was visualizing incoming data (which actually streams/updates at audio-rate). I was calling repaint() in the timer callback instead of repainting just the slider region and so the entire component was repainting at 1/50 of a second. Passing just the slider/rectangle area into repaint seems to help out quite a bit, although my AudioRecorder waveform display is still eats up more CPU than I’d like, I think because of how much visible area the wavform display is repainting at 1/50 second intervals (the display is basically the same display from the JUCE demo…)

Will keep playing around :slight_smile: