GPROF(1)

๐Ÿ“ฆ version 2.45, in ubuntu questing

โœจ GPROF(1) โœจ GNU ๐Ÿ’–

๐Ÿซถ NAME ๐Ÿซถ

okay so the name is just gprof, and it's all about displaying call graph profile data ๐Ÿ“Šโœจ

๐ŸŒธ SYNOPSIS ๐ŸŒธ

okay bestie, here's the whole big list of ways you can call it ๐Ÿ‘€

gprof [ -[abcDhilLrsTvwxyz] ] [ -[ABCeEfFJnNOpPqQRStZ][name] ]
 [ -I dirs ] [ -d[num] ] [ -k from/to ]
 [ -m min-count ] [ -R map_file ] [ -t table-length ]
 [ --[no-]annotated-source[=name] ]
 [ --[no-]exec-counts[=name] ]
 [ --[no-]flat-profile[=name] ] [ --[no-]graph[=name] ]
 [ --[no-]time=name] [ --all-lines ] [ --brief ]
 [ --debug[=level] ] [ --function-ordering ]
 [ --file-ordering map_file ] [ --directory-path=dirs ]
 [ --display-unused-functions ] [ --file-format=name ]
 [ --file-info ] [ --help ] [ --line ] [ --inline-file-names ]
 [ --min-count=n ] [ --no-static ] [ --print-path ]
 [ --separate-files ] [ --static-call-graph ] [ --sum ]
 [ --table-length=len ] [ --traditional ] [ --version ]
 [ --width=n ] [ --ignore-non-functions ]
 [ --demangle[=STYLE] ] [ --no-demangle ]
 [--external-symbol-table=name]
 [ image-file ] [ profile-file ... ]

๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

okay so gprof is literally the tool that makes a execution profile for C, Pascal, or Fortran77 programs ๐Ÿ’… it's giving performance detective ๐Ÿ” every routine's cost gets folded into the profile of whoever called it, so nothing gets left out ๐ŸŒˆ

the profile data comes from the call graph profile file (gmon.out is the default) ๐Ÿ“ that file gets created by programs compiled with the -pg option of cc, pc, and f77. the -pg option also links in versions of the library routines that were compiled for profiling, so the library stuff shows up too โœจ

then gprof reads the given object file (the default is a.out) and matches up its symbol table with the call graph profile from gmon.out ๐Ÿงฉ and if you give it more than one profile file, the output shows the sum of the profile info from all of them. main character energy, collecting all the receipts ๐Ÿงพ๐Ÿ’œ

โš ๏ธ bestie, real talk: if you compile your binaries with gcc 2.95.x or 3.0, you may need to add the -fprofile-arcs to the compile command line so the call graphs actually get stored properly in gmon.out. otherwise the data can be incomplete, and nobody wants that ๐Ÿ˜ญ

okay now the math part ๐Ÿค“ gprof works out how much time gets spent in each routine. next, those times get propagated along the edges of the call graph. cycles get discovered, and any calls into a cycle end up sharing the time of that cycle. it's like the whole thing is passing the tea around ๐Ÿต

there are a few different outputs you can get from the analysis:

  • the flat profile ๐Ÿ“‹ shows how much time your program spent in each function, and how many times that function got called. if you just want to know which functions are burning the most cycles, this is the one, and it says it concisely ๐Ÿ’…
  • the call graph ๐Ÿ•ธ๏ธ shows, for each function, which functions called it, which other functions it called, and how many times. it also estimates how much time got spent in the subroutines of each function. this is where you can spot calls that use a lot of time and think about getting rid of them ๐Ÿ‘€
  • the annotated source listing ๐Ÿ“ is a copy of your program's source code, labeled with the number of times each line was executed. so cute, you can see exactly which lines are the hot ones ๐Ÿ”ฅ

๐ŸŽ€ OPTIONS ๐ŸŽ€

these options decide which of the several output formats gprof should produce ๐Ÿ’–

a lot of these options can take an optional symspec to pick which functions get included or excluded ๐ŸŽฏ and you can repeat these options with different symspecs to include or exclude whole sets of symbols. it's giving customisable ๐Ÿ’…

heads up: if you specify any of these options, it overrides the default (-p -q), which would normally print a flat profile and call graph analysis for all functions. so you're basically taking the wheel ๐Ÿš—โœจ

  • -A[symspec], --annotated-source[=symspec] โ€” this one makes gprof print annotated source code ๐Ÿ“ if you give it a symspec, it only prints output for the matching symbols ๐ŸŽฏ
  • -b, --brief โ€” with this, gprof skips the verbose blurbs that explain what all the fields in the tables mean ๐Ÿ™ˆ super useful if you're printing the output or you're just tired of seeing those blurbs
  • -B โ€” this makes gprof print the call graph analysis ๐Ÿ•ธ๏ธ
  • -C[symspec], --exec-counts[=symspec] โ€” this prints a tally of functions and how many times each one was called ๐Ÿงฎ if you add a symspec, the tally only shows the matching symbols ๐ŸŽฏ

if your profile data file has basic-block count records, then pairing -l with -C makes it tally and display the basic-block execution counts too ๐Ÿค“

  • -i, --file-info โ€” this shows summary info about the profile data file(s) and then exits ๐Ÿ‘‹ you get the number of histogram, call graph, and basic-block count records ๐Ÿ“Š
  • -I dirs, --directory-path=dirs โ€” this gives a list of search directories where gprof can find source files ๐Ÿ“‚ you can also use the environment variable GPROF_PATH to pass that same info along ๐Ÿงš it's mostly used for annotated source output
  • -J[symspec], --no-annotated-source[=symspec] โ€” the opposite energy ๐Ÿ™…โ€โ™€๏ธ this makes gprof not print annotated source code. if you add a symspec, gprof still prints annotated source, but leaves out the matching symbols ๐Ÿซ 
  • -L, --print-path โ€” normally the source filenames get printed with the path part hidden ๐Ÿ™ˆ with -L, you get the full pathname instead ๐Ÿ—บ๏ธ it comes from the symbolic debugging info in the image file and is relative to the directory where the compiler was invoked
  • -p[symspec], --flat-profile[=symspec] โ€” this makes gprof print a flat profile ๐Ÿ“‹ with a symspec, you only get a flat profile for the matching symbols ๐ŸŽฏ
  • -P[symspec], --no-flat-profile[=symspec] โ€” this one suppresses the flat profile ๐Ÿšซ if you add a symspec, gprof prints a flat profile but excludes the matching symbols ๐Ÿ’…
  • -q[symspec], --graph[=symspec] โ€” this makes gprof print the call graph analysis ๐Ÿ•ธ๏ธ with a symspec, you only get the call graph for matching symbols and their children ๐Ÿ‘ถ
  • -Q[symspec], --no-graph[=symspec] โ€” this suppresses the call graph ๐Ÿšซ with a symspec, gprof prints a call graph but excludes the matching symbols ๐Ÿ™ƒ
  • -t, --table-length=num โ€” this lists the num most active source lines in each source file when source annotation is turned on ๐Ÿ”ฅ the default is 10 ๐Ÿ”Ÿ
  • -y, --separate-files โ€” this one only affects annotated source output ๐Ÿ“ normally gprof prints annotated source files to standard-output. with this option, the annotated source for a file named path/filename gets generated in the file filename-ann ๐Ÿ“
โš ๏ธ if the underlying file system would truncate filename-ann so it overwrites the original filename, gprof writes the annotated source to filename.ann instead. if the original file name has an extension, that extension gets replaced with .ann ๐Ÿ˜ฌ
  • -Z[symspec], --no-exec-counts[=symspec] โ€” this stops gprof from printing the tally of functions and how many times each was called ๐Ÿ™… with a symspec, the tally still prints, but the matching symbols get excluded ๐Ÿซถ
  • -r, --function-ordering โ€” this makes gprof print a suggested function ordering for your program, based on the profiling data ๐Ÿง  the ordering may improve paging, tlb and cache behavior, but only on systems that support arbitrary ordering of functions in an executable ๐Ÿš€

the exact details of how to force the linker to place functions in a particular order are system dependent and out of scope for this manual ๐Ÿ™ˆ

  • -R map_file, --file-ordering map_file โ€” this prints a suggested .o link line ordering for your program, based on profiling data ๐Ÿงฉ it can help paging, tlb and cache behavior on systems that don't support arbitrary ordering of functions in an executable ๐ŸŒˆ

bestie, it's highly recommended to use the -a argument with this option ๐Ÿ’œ

the map_file is a pathname to a file that maps function names to object files ๐Ÿ—บ๏ธ the format is similar to the output of the program nm, kinda like this:

c-parse.o:00000000 T yyparse
c-parse.o:00000004 C yyerrflag
c-lang.o:00000000 T maybe_objc_method_name
c-lang.o:00000000 T print_lang_statistics
c-lang.o:00000000 T recognize_objc_keyword
c-decl.o:00000000 T print_lang_identifier
c-decl.o:00000000 T print_lang_type
...

to make a map_file with GNU nm, type a command like nm --extern-only --defined-only -v --print-file-name program-name ๐Ÿ’ปโœจ

  • -T, --traditional โ€” this makes gprof print its output in "traditional" BSD style ๐ŸŽ€
  • -w width, --width=width โ€” this sets the width of the output lines to width ๐Ÿ“ right now it's only used when printing the function index at the bottom of the call graph ๐Ÿฆ‹
  • -x, --all-lines โ€” another annotated-source-only option ๐Ÿ“ by default, only the lines at the beginning of a basic-block get annotated. with this one, every line in a basic-block gets annotated by repeating the annotation for the first line ๐Ÿ” it works kinda like tcov's -a ๐Ÿค“
  • --demangle[=style], --no-demangle โ€” these control whether C++ symbol names get demangled when printing output ๐Ÿ’… the default is to demangle symbols, and --no-demangle turns that off. different compilers have different mangling styles, so the optional style argument lets you pick the one that matches your compiler ๐ŸŒธ

๐ŸŒท Analysis Options ๐ŸŒท

  • -a, --no-static โ€” this stops gprof from printing statically declared (private) functions ๐Ÿซฅ these are the functions whose names aren't listed as global, and which aren't visible outside the file, function, or block where they were defined. the time spent in these functions, and the calls to and from them, all get attributed to the function that was loaded directly before it in the executable file ๐Ÿงพ this option affects both the flat profile and the call graph ๐Ÿ’–

to be continued in part 2, bestie ๐ŸŒˆโœจ

  • -c, --static-call-graph โ€” okay so this one is a sneaky little heuristic ๐Ÿ•ต๏ธโ€โ™€๏ธ. It pokes around the text space of the object file and spots function calls in the binary machine code. Normal call graph records only show up when a function actually gets entered, so this option finds children that could have been called but never were. Calls to functions that weren't compiled with profiling enabled get caught too, but only if they have symbol table entries. Calls into dynamic library routines are usually invisible to it ๐Ÿ™ˆ. Parents or children found this way show up in the call graph with a call count of 0 ๐Ÿ’….
  • -D, --ignore-non-functions โ€” this one tells gprof to ignore any symbols that aren't known to be functions ๐Ÿงน. On systems that support it (Solaris and HPUX, for example), you get more accurate profile data โœจ.
  • -k from/to โ€” lets you delete arcs from the call graph. Any arc going from symbols matching symspec from to symbols matching symspec to gets yeeted ๐Ÿ—‘๏ธ.
  • -l, --line โ€” turns on line-by-line profiling ๐Ÿ“, so histogram hits get charged to individual source lines instead of whole functions. Heads up: this only works with programs compiled by older versions of the gcc compiler. Newer gcc versions are built to work with the gcov tool instead ๐Ÿ™…โ€โ™€๏ธ. If the program was compiled with basic-block counting enabled, this option also tells you how many times each line ran ๐Ÿ”ข. It's super helpful for finding where inside a huge function the time is going, but ngl it makes gprof way slower and makes statistical inaccuracies louder ๐Ÿ˜ญ.
  • --inline-file-names โ€” prints the source file after each symbol in both the flat profile and the call graph ๐Ÿ“. If you pair it with the -L option, you get the full path to the file ๐Ÿ›ค๏ธ.
  • -m num, --min-count=num โ€” only affects execution count output ๐Ÿ”ข. Symbols executed fewer than num times get hidden. Bye, low-key functions ๐Ÿ‘‹.
  • -nsymspec, --time=symspec โ€” the -n option makes gprof, during its call graph analysis, only propagate times for symbols matching symspec ๐ŸŽฏ.
  • -Nsymspec, --no-time=symspec โ€” the -n option makes gprof, during its call graph analysis, not propagate times for symbols matching symspec ๐Ÿšซ.
  • -Sfilename, --external-symbol-table=filename โ€” tells gprof to read an external symbol table file, like /proc/kallsyms, instead of reading the symbol table from the object file (the default is a.out) ๐Ÿงš. This is the move for profiling kernel modules ๐Ÿ”ฅ.
  • -z, --display-unused-functions โ€” with this on, gprof lists every function in the flat profile, even ones that were never called and didn't spend any time ๐Ÿฆ‹. It pairs beautifully with the -c option if you want to find routines that never got called ๐Ÿ•ต๏ธโ€โ™€๏ธ.

โœจ Miscellaneous Options โœจ

  • -d[num], --debug[=num] โ€” sets debugging options ๐Ÿ›. If you don't give a num, you get all debugging turned on ๐ŸŒˆ.
  • -h, --help โ€” prints the command line usage ๐Ÿ†˜.
  • -Oname, --file-format=name โ€” picks the format of the profile data files ๐Ÿ“‚. The recognized formats are auto (the default), bsd, 4.4bsd, magic, and prof (not yet supported) ๐Ÿ™ƒ.
  • -s, --sum โ€” gprof summarizes the info from all the profile data files it read and writes it into a new file called gmon.sum ๐Ÿง. That file holds everything from the input files. Fun twist: gmon.sum can be one of the input files too, which merges the data from the other inputs into it ๐Ÿซถ.

Later on, you can run gprof again without -s to analyze the cumulative data stored in gmon.sum ๐Ÿ“Š.

  • -v, --version โ€” prints the current version number and then exits ๐Ÿ”ข.

๐Ÿ™…โ€โ™€๏ธ Deprecated Options ๐Ÿ™…โ€โ™€๏ธ

These options have been replaced with newer versions that use symspecs. Use the newer stuff, bestie ๐Ÿ’–.
  • -e function_name โ€” tells gprof to skip printing info about function_name (and its children...) in the call graph ๐Ÿ‘ป. The function still shows up as a child of any functions that call it, but its index number displays as [not printed]. You can give more than one -e option, but each one only takes a single function_name.
  • -E function_name โ€” works like -e, but the time spent in the function (and any children who weren't called from anywhere else) won't count toward the percentages-of-time in the call graph ๐Ÿงฎ. Again, you can use more than one -E, with one function_name each.
  • -f function_name โ€” limits the call graph to function_name and its children (and their children...) ๐Ÿ”. Multiple -f options are allowed, one function_name per option.
  • -F function_name โ€” works like -f, but only the time spent in the function and its children (and their children...) gets used for total-time and percentages-of-time in the call graph โฑ๏ธ. Multiple -F options are allowed, one function_name each. The -F option overrides the -E option ๐Ÿ‘‘.

๐Ÿ“ FILES ๐Ÿ“

  • a.out โ€” the namelist and text space ๐Ÿงพ.
  • gmon.out โ€” dynamic call graph and profile ๐Ÿ“ˆ.
  • gmon.sum โ€” summarized dynamic call graph and profile ๐Ÿง.

๐Ÿ› BUGS ๐Ÿ›

The granularity of the sampling is shown, but it stays statistical at best ๐ŸŽฒ. We assume the time for each execution of a function can be expressed as the total time for the function divided by the number of times it's called. So the time propagated along the call graph arcs to a function's parents is directly proportional to how many times that arc gets traversed ๐Ÿ”.

Parents that aren't profiled themselves will have the time of their profiled children propagated to them. They'll look like they were spontaneously invoked in the call graph listing, and their time won't be propagated any further ๐Ÿ‘€. Signal catchers are similar: even when profiled, they appear spontaneous (for more obscure reasons ๐ŸŒ€). Any profiled children of signal catchers should still get their times propagated properly, unless the signal catcher was invoked during the execution of the profiling routine. In that case, all is lost ๐Ÿ’€.

The profiled program must call exit(2) or return normally for the profiling information to be saved in the gmon.out file. No exit, no data, no cap ๐Ÿ˜ญ.

๐Ÿ”— SEE ALSO ๐Ÿ”—

cc(1), prof(1), and the Info entry for gprof ๐Ÿ“š.

"An Execution Profiler for Modular Programs", by S. Graham, P. Kessler, M. McKusick; Software - Practice and Experience, Vol. 13, pp. 671-685, 1983 ๐Ÿง.

"gprof: A Call Graph Execution Profiler", by S. Graham, P. Kessler, M. McKusick; Proceedings of the SIGPLAN '82 Symposium on Compiler Construction, SIGPLAN Notices, Vol. 17, No 6, pp. 120-126, June 1982 ๐Ÿ“.

Copyright (c) 1988-2025 Free Software Foundation, Inc. ๐Ÿ’œ

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License" ๐Ÿ“œ.


That's the whole tea, bestie! ๐ŸŒˆ This page belongs to binutils 2.45 and was last updated on 2025-12-03, so go profile something iconic and send me the call graph ๐Ÿ’–โœจ๐Ÿซถ

๐Ÿ“ฆ where this page comes from