How to profile from the command line on Mac OS X?

prosseek picture prosseek · Mar 27, 2015 · Viewed 8.2k times · Source

I'm trying to profile C/C++ code on Mac OS X using command line tools, I use -pg option with gcc to run gprof on Linux, but I can't seem to find the gprof on Mac even though I have a description in this page: Additional Command-Line Tools (iOS) or Additional Command-Line Tools (mac).

gprof:Produces execution profiles based on an execution analysis of a program.

I installed command line tools, so other command line tools such as otool and atos are available. I googled to find this page (https://apple.stackexchange.com/questions/154289/installing-gprof-on-mac) that says gprof is not supported, but I'm not sure when I have an Apple doc describing the tool; anyway, I tried to use brew to download gprof, but it didn't work.

I found Attempting to use gprof with C++ code on a Mac, but I have no output with instruments -t. I also found Profiling c++ on mac os x, but I don't want to open Instruments, as I would like to automate some of the processes and try to keep cross platform system.

  • How to use gprof on Mac OS X? I use OS X 10.10.
  • How can I profile from the command line, with or without gprof?

Answer

osgx picture osgx · Jul 1, 2016

It is strange to hear that there is no gprof profiler for OSX. OSX is certified unix and the profiler of unix is gprof (based on profil syscall/library function which is there: https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/profil.2.html).

There are problems with GNU gprof (part of binutils) according to https://apple.stackexchange.com/questions/154289/installing-gprof-on-mac (2014; thanks to Sreekanth Nagareddy user - deleted answer), brew install -v binutils "*** This configuration is not supported in the following subdirectories: .. ld gas gprof"; OSX is not listed in GNU gprof readme: http://code.metager.de/source/xref/gnu/src/gprof/README (2012) in "Supported Platforms" (only OSF/1, SunOS, Solaris, HP-UX listed; I think it should work on Hurd and works on Linuxes).

But there is also BSD implementation of gprof (check https://en.wikipedia.org/wiki/gprof for history and references). Didn't try to get it running on OSX (have no OSX nor bitten apples newer than 1995 desktop&notebook).

There are different sources of BSD gprof, for example, FreeBSD's version (https://github.com/freebsd/freebsd/tree/af3e10e5a78d3af8cef6088748978c6c612757f0/usr.bin/gprof) or ancient 4.3BSD original http://www.retro11.de/ouxr/43bsd/usr/src/ucb/gprof/. Both variants have no support of Mach-O format used in OSX.

There is even Apple's own gprof (based on BSD gprof from NetBSD/OpenBSD) in cctools of Darwin (Darwin is UNIX part both kernel and user-space of OSX; it is/was/will open-source): https://github.com/LeoTestard/Darwin/tree/master/cctools/gprof / https://github.com/darwin-on-arm/darwin-sdk/tree/master/cctools/gprof / http://src.gnu-darwin.org/src/usr.bin/gprof/gprof.c.html (some older mix of FreeBSD code and GNU crazy ideas of freedom).

The availability of gprof may depend on exact OSX version or Xcode version/packages; there were gprof for 10.6.1, according to http://louise.hu/poet/gprof-on-osx/ or on some version from 2012 - https://rachelbythebay.com/w/2012/09/14/mac/ or even in 2001: http://lists.apple.com/archives/darwin-development/2001/Apr/msg00617.html

There is variant of using instruments (part of Xcode Tools?) in command-line, don't know how exactly, but know that instruments is modern and feature-rich profiler.

There is also iprofiler command-line interface to collect profiles for Instruments.app, just noted man page of it https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/iprofiler.1.html (part of Xcode Tools version 5.0; manpage from legacy part of site).

There are third-party profilers, declared to support OSX. I know two of them: valgrind and gperftools (google-perftools).

valgrind is not a profiler; it is a (slow) dynamic instrumentation platform with many tools built on top of it. It includes two tools, capable of profiling: callgrind and cachegrind. Valgrind and both tools are not native profiler, they do not profile application as it will run on real cpu in real life. Instead, valgrind executes program on the virtual machine and callgrind/cachegrind instruments machine code with counters.

callgrind (http://valgrind.org/docs/manual/cl-manual.html) uses counter per linear block of instructions to count "how many times every instruction will be executed" ("Ir" event, used to get profile - sort functions by percent of time used); it also records calls/returns to build callgraph. "Ir" event count is correct to get instruction execution counts (it may also emulate branch prediction); but it can't be used to estimate real running time. Real cpu (high performance cpus called superscalar; out-of-order cpus are superscalar too) able to execute more than one instruction per cpu clock cycle; and it is also often incapable of executing any instruction because they may want some data to be started (data from far cache or from memory or from syscall or from other high-latency instruction; or cpu mispredicted branch leads to instruction address not yet read/decoded). Most progressive cpus may even not execute some commands (some can execute up to 8 "nop"s per cycle, several Intel's Sandy/Ivy Bridges and newer will not spend any time on "xor eax,eax" to write zero into register; they just remap next register usage to zeroed physical register). callgrind has typical 10-20 slowdown on profiling run compared to real run on hardware CPU.

Cachegrind implements same instrumentation as callgrind ("Ir", branches), but also can emulate cache hierarchy (cache loads/stores/misses events). And it is slower than callgrind.

Output from callgrind and cachegrind can be viewed with GUI tool kcachegrind (http://kcachegrind.sourceforge.net/, it may work in OS) or in command-line tool callgrind_annotate.

Other tool is gperftools (google-perftools, https://github.com/gperftools/gperftools), which run the program on real CPU. To use it, install it with homebrew, then link the program with libprofiler (add -Lpath_to_installed_gperftools -lprofiler) and run with CPUPROFILE environment variable set to some filename (CPUPROFILE=profile01 ./the_program). It will profile the program using interval timer (setitimer) and output profiling data to the filename, defined inCPUPROFILEenv var. Then you can view profile data in command-line or with svg/web browser usingpprofperl script from gperftools (pprof ./the_program profile01`).