Writing

Feed Software, technology, sysadmin war stories, and more.

Friday, September 14, 2012

Attempting to use gprof with C++ code on a Mac

It's followup time for yesterday's post in which I talked about using a power meter to gauge load when developing on my Mac. It's one of those "ha ha only serious" things, in that using a power meter is kind of ridiculous, especially if it's a consumer item with no graphing or other history, but so is the tool situation on Mac OS.

This morning, that post made it onto Hacker News, and there, a variety of things came out. First, as I write this, the top comment says that "gprof works fine for me". Okay, so let's take that one first. Here's a dumb little demo program that does nothing but chew CPU:

#include <stdio.h>
#include <stdlib.h>
 
static void burn_cpu() {
  unsigned int acc = 0;
  for (int i = 0; i < 1048576; ++i) {
    acc += random() * 65536;
  }
}
 
int main(int argc, char** argv) {
  for (int i = 0; i < 32; ++i) {
    burn_cpu();
  }
 
  return 0;
}

So, I compile it, and run it, and verify that yes, it does beat on the CPU rather nicely:

rachel 54574 100.0 0.0 2432744 500 s005 R+ 5:16PM 0:01.75 ./prof

Fantastic, then. Now I'll recompile it with gcc's "-pg" switch, and then run it again. This should give me some output gunk in my current working directory.

Rachels-Mac-mini:prof rachel$ g++ -pg -Wall -o prof prof.cc
Rachels-Mac-mini:prof rachel$ ./prof
Rachels-Mac-mini:prof rachel$ ls
prof    prof.cc
Rachels-Mac-mini:prof rachel$ 

... huh? So, okay, take the same code, plop it on a Linux box, compile it with the same command and then run it, and ...

$ mkdir prof
$ cd prof
$ cat > prof.cc
[ ... I pasted it straight into the xterm here ... ]
^D
$ g++ -pg -Wall -o prof prof.cc && ./prof
$ ls
gmon.out  prof  prof.cc
$ 

... and there's my gmon output. Now I can run gprof, and...

Flat profile:
 
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
101.20      0.09     0.09       32     2.85     2.85  burn_cpu()

... that's what I expected to see. For whatever reason, it just doesn't kick in when running on my Mountain Lion machine. I don't feel like going on another spelunking expedition into their compiler and/or C library source to see why just now.

Other things which have been mentioned (some by me, in the original post) are shark and instruments. Okay, shark.

Rachels-Mac-mini:prof rachel$ which shark
Rachels-Mac-mini:prof rachel$ 

Guess not. Spotlight is similarly clueless. But hey, /usr/bin/instruments does exist, so let's try that.

Rachels-Mac-mini:prof rachel$ instruments ./prof

Instruments Usage Error : No template (-t) specified

instruments, version 4.4 (4445)

usage: instruments [-t template] [-D document] [-l timeLimit] [-i #] [-w device] [[-p pid] | [application [-e variable value] [argument ...]]]

Apparently it does not have a default template. I ran 'instruments -s' (listed in the man page, but not shown in the help text above) to see what my options were. I was "rewarded" with my choice of 29 different templates, which I will not paste in here. Five of those are for "iPhoneOS" (hey, what happened to calling it "iOS"?) and so can be ignored. Removing OpenGL and animation and file stuff brings it down to 18.

I'll just pick one that looks promising and see what it tells me.

Rachels-Mac-mini:prof rachel$ instruments -t /Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate ./prof

instruments: Instruments wants permission to analyze other processes.

Type your password to allow this.

Name (rachel):

Password:

_RegisterApplication(), FAILED TO establish the default connection to the WindowServer, _CGSDefaultConnection() is NULL.

2012-09-15 00:30:17 +0000 Fail: An error occurred while trying to run the script.

2012-09-15 00:30:18 +0000 Fail: The target application appears to have died

Instruments Trace Complete (Duration : 7.126134s; Output : /Users/rachel/prof/instrumentscli0.trace)

Rachels-Mac-mini:prof rachel$

Did I mention that my Mini is headless most of the time, and thus I am not logged in to the GUI at all? Yep. I ssh into it to work on things. That's not too surprising for a "Unix" box, right? Apparently it really wants to do something graphical here. I'll humor it and remote in, even though I really do not like having such things in the middle of my workflow.

2012-09-15 00:34:29 +0000 Fail: An error occurred while trying to run the script.

2012-09-15 00:34:29 +0000 Fail: The target application appears to have died

Instruments Trace Complete (Duration : 7.343545s; Output : /Users/rachel/prof/instrumentscli2.trace)

Righto. Opening that directory in the actual Instruments.app graphical program yields the same error, so it seems it really did not get anything useful from that run.

"Choose target" in there doesn't seem to allow me to pick a boring old C++ binary sitting on the disk. I suppose I could start it up and then attach to the running process, though. This involves picking it out of a dropdown list that's much taller than my screen is. Good luck finding "prof (57631)" before it ends!

If I rig the program to stay around for a while, then I can in fact (eventually) find it in the list, attach to it, and get a capture. I let it run for 14 seconds, and then killed the process and stopped recording. It is presently sitting there doing nothing in particular while the fan spins way up. Finally, I get this:

Instruments UI

I'm sure what it provides is useful to someone, but it's a looooooong way from the function listing I got from gprof. The function listing is all I really needed.

I still like my Macs for the things they do well. It's just a matter of realizing that this kind of work is not one of those things.