[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gprof
's Output
gprof
can produce several different output styles, the
most important of which are described below. The simplest output
styles (file information, execution count, and function and file ordering)
are not described here, but are documented with the respective options
that trigger them.
See section 4.1 Output Options.
5.1 The Flat Profile The flat profile shows how much time was spent executing directly in each function. 5.2 The Call Graph The call graph shows which functions called which others, and how much time each function used when its subroutine calls are included. 5.3 Line-by-line Profiling gprof
can analyze individual source code lines5.4 The Annotated Source Listing The annotated source listing displays source code labeled with execution counts
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The flat profile shows the total amount of time your program spent executing each function. Unless the `-z' option is given, functions with no apparent time spent in them, and no apparent calls to them, are not mentioned. Note that if a function was not compiled for profiling, and didn't run long enough to show up on the program counter histogram, it will be indistinguishable from a function that was never called.
This is part of a flat profile for a small program:
Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls ms/call ms/call name 33.34 0.02 0.02 7208 0.00 0.00 open 16.67 0.03 0.01 244 0.04 0.12 offtime 16.67 0.04 0.01 8 1.25 1.25 memccpy 16.67 0.05 0.01 7 1.43 1.43 write 16.67 0.06 0.01 mcount 0.00 0.06 0.00 236 0.00 0.00 tzset 0.00 0.06 0.00 192 0.00 0.00 tolower 0.00 0.06 0.00 47 0.00 0.00 strlen 0.00 0.06 0.00 45 0.00 0.00 strchr 0.00 0.06 0.00 1 0.00 50.00 main 0.00 0.06 0.00 1 0.00 0.00 memcpy 0.00 0.06 0.00 1 0.00 10.11 print 0.00 0.06 0.00 1 0.00 0.00 profil 0.00 0.06 0.00 1 0.00 50.00 report ... |
The functions are sorted by first by decreasing run-time spent in them, then by decreasing number of calls, then alphabetically by name. The functions `mcount' and `profil' are part of the profiling apparatus and appear in every flat profile; their time gives a measure of the amount of overhead due to profiling.
Just before the column headers, a statement appears indicating how much time each sample counted as. This sampling period estimates the margin of error in each of the time figures. A time figure that is not much larger than this is not reliable. In this example, each sample counted as 0.01 seconds, suggesting a 100 Hz sampling rate. The program's total execution time was 0.06 seconds, as indicated by the `cumulative seconds' field. Since each sample counted for 0.01 seconds, this means only six samples were taken during the run. Two of the samples occurred while the program was in the `open' function, as indicated by the `self seconds' field. Each of the other four samples occurred one each in `offtime', `memccpy', `write', and `mcount'. Since only six samples were taken, none of these values can be regarded as particularly reliable. In another run, the `self seconds' field for `mcount' might well be `0.00' or `0.02'. See section 6.1 Statistical Sampling Error, for a complete discussion.
The remaining functions in the listing (those whose `self seconds' field is `0.00') didn't appear in the histogram samples at all. However, the call graph indicated that they were called, so therefore they are listed, sorted in decreasing order by the `calls' field. Clearly some time was spent executing these functions, but the paucity of histogram samples prevents any determination of how much time each took.
Here is what the fields in each line mean:
% time
cumulative seconds
self seconds
calls
self ms/call
total ms/call
name
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The call graph shows how much time was spent in each function and its children. From this information, you can find functions that, while they themselves may not have used much time, called other functions that did use unusual amounts of time.
Here is a sample call from a small program. This call came from the
same gprof
run as the flat profile example in the previous
chapter.
granularity: each sample hit covers 2 byte(s) for 20.00% of 0.05 seconds index % time self children called name <spontaneous> [1] 100.0 0.00 0.05 start [1] 0.00 0.05 1/1 main [2] 0.00 0.00 1/2 on_exit [28] 0.00 0.00 1/1 exit [59] ----------------------------------------------- 0.00 0.05 1/1 start [1] [2] 100.0 0.00 0.05 1 main [2] 0.00 0.05 1/1 report [3] ----------------------------------------------- 0.00 0.05 1/1 main [2] [3] 100.0 0.00 0.05 1 report [3] 0.00 0.03 8/8 timelocal [6] 0.00 0.01 1/1 print [9] 0.00 0.01 9/9 fgets [12] 0.00 0.00 12/34 strncmp <cycle 1> [40] 0.00 0.00 8/8 lookup [20] 0.00 0.00 1/1 fopen [21] 0.00 0.00 8/8 chewtime [24] 0.00 0.00 8/16 skipspace [44] ----------------------------------------------- [4] 59.8 0.01 0.02 8+472 <cycle 2 as a whole> [4] 0.01 0.02 244+260 offtime <cycle 2> [7] 0.00 0.00 236+1 tzset <cycle 2> [26] ----------------------------------------------- |
The lines full of dashes divide this table into entries, one for each function. Each entry has one or more lines.
In each entry, the primary line is the one that starts with an index number in square brackets. The end of this line says which function the entry is for. The preceding lines in the entry describe the callers of this function and the following lines describe its subroutines (also called children when we speak of the call graph).
The entries are sorted by time spent in the function and its subroutines.
The internal profiling function mcount
(see section 5.1 The Flat Profile)
is never mentioned in the call graph.
5.2.1 The Primary Line Details of the primary line's contents. 5.2.2 Lines for a Function's Callers Details of caller-lines' contents. 5.2.3 Lines for a Function's Subroutines Details of subroutine-lines' contents. 5.2.4 How Mutually Recursive Functions Are Described When there are cycles of recursion, such as a
callsb
callsa
...
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The primary line in a call graph entry is the line that describes the function which the entry is about and gives the overall statistics for this function.
For reference, we repeat the primary line from the entry for function
report
in our main example, together with the heading line that
shows the names of the fields:
index % time self children called name ... [3] 100.0 0.00 0.05 1 report [3] |
Here is what the fields in the primary line mean:
index
Each cross-reference to a function, as a caller or subroutine of another, gives its index number as well as its name. The index number guides you if you wish to look for the entry for that function.
% time
The time spent in this function is counted again for the callers of this function. Therefore, adding up these percentages is meaningless.
self
seconds
field
for this function in the flat profile.
children
self
and children
entries of the children listed directly below this
function.
called
If the function called itself recursively, there are two numbers, separated by a `+'. The first number counts non-recursive calls, and the second counts recursive calls.
In the example above, the function report
was called once from
main
.
name
If the function is part of a cycle of recursion, the cycle number is
printed between the function's name and the index number
(see section 5.2.4 How Mutually Recursive Functions Are Described). For example, if function gnurr
is part of
cycle number one, and has index number twelve, its primary line would
be end like this:
gnurr <cycle 1> [12] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A function's entry has a line for each function it was called by. These lines' fields correspond to the fields of the primary line, but their meanings are different because of the difference in context.
For reference, we repeat two lines from the entry for the function
report
, the primary line and one caller-line preceding it, together
with the heading line that shows the names of the fields:
index % time self children called name ... 0.00 0.05 1/1 main [2] [3] 100.0 0.00 0.05 1 report [3] |
Here are the meanings of the fields in the caller-line for report
called from main
:
self
report
itself when it was
called from main
.
children
report
when report
was called from main
.
The sum of the self
and children
fields is an estimate
of the amount of time spent within calls to report
from main
.
called
report
was called from main
,
followed by the total number of non-recursive calls to report
from
all its callers.
name and index number
report
to which this line applies,
followed by the caller's index number.
Not all functions have entries in the call graph; some
options to gprof
request the omission of certain functions.
When a caller has no entry of its own, it still has caller-lines
in the entries of the functions it calls.
If the caller is part of a recursion cycle, the cycle number is printed between the name and the index number.
If the identity of the callers of a function cannot be determined, a dummy caller-line is printed which has `<spontaneous>' as the "caller's name" and all other fields blank. This can happen for signal handlers.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A function's entry has a line for each of its subroutines--in other words, a line for each other function that it called. These lines' fields correspond to the fields of the primary line, but their meanings are different because of the difference in context.
For reference, we repeat two lines from the entry for the function
main
, the primary line and a line for a subroutine, together
with the heading line that shows the names of the fields:
index % time self children called name ... [2] 100.0 0.00 0.05 1 main [2] 0.00 0.05 1/1 report [3] |
Here are the meanings of the fields in the subroutine-line for main
calling report
:
self
report
when report
was called from main
.
children
report
when report
was called from main
.
The sum of the self
and children
fields is an estimate
of the total time spent in calls to report
from main
.
called
report
from main
followed by the total number of non-recursive calls to report
.
This ratio is used to determine how much of report
's self
and children
time gets credited to main
.
See section 6.2 Estimating children
Times.
name
main
to which this line applies,
followed by the subroutine's index number.
If the caller is part of a recursion cycle, the cycle number is printed between the name and the index number.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The graph may be complicated by the presence of cycles of
recursion in the call graph. A cycle exists if a function calls
another function that (directly or indirectly) calls (or appears to
call) the original function. For example: if a
calls b
,
and b
calls a
, then a
and b
form a cycle.
Whenever there are call paths both ways between a pair of functions, they
belong to the same cycle. If a
and b
call each other and
b
and c
call each other, all three make one cycle. Note that
even if b
only calls a
if it was not called from a
,
gprof
cannot determine this, so a
and b
are still
considered a cycle.
The cycles are numbered with consecutive integers. When a function belongs to a cycle, each time the function name appears in the call graph it is followed by `<cycle number>'.
The reason cycles matter is that they make the time values in the call
graph paradoxical. The "time spent in children" of a
should
include the time spent in its subroutine b
and in b
's
subroutines--but one of b
's subroutines is a
! How much of
a
's time should be included in the children of a
, when
a
is indirectly recursive?
The way gprof
resolves this paradox is by creating a single entry
for the cycle as a whole. The primary line of this entry describes the
total time spent directly in the functions of the cycle. The
"subroutines" of the cycle are the individual functions of the cycle, and
all other functions that were called directly by them. The "callers" of
the cycle are the functions, outside the cycle, that called functions in
the cycle.
Here is an example portion of a call graph which shows a cycle containing
functions a
and b
. The cycle was entered by a call to
a
from main
; both a
and b
called c
.
index % time self children called name ---------------------------------------- 1.77 0 1/1 main [2] [3] 91.71 1.77 0 1+5 <cycle 1 as a whole> [3] 1.02 0 3 b <cycle 1> [4] 0.75 0 2 a <cycle 1> [5] ---------------------------------------- 3 a <cycle 1> [5] [4] 52.85 1.02 0 0 b <cycle 1> [4] 2 a <cycle 1> [5] 0 0 3/6 c [6] ---------------------------------------- 1.77 0 1/1 main [2] 2 b <cycle 1> [4] [5] 38.86 0.75 0 1 a <cycle 1> [5] 3 b <cycle 1> [4] 0 0 3/6 c [6] ---------------------------------------- |
(The entire call graph for this program contains in addition an entry for
main
, which calls a
, and an entry for c
, with callers
a
and b
.)
index % time self children called name <spontaneous> [1] 100.00 0 1.93 0 start [1] 0.16 1.77 1/1 main [2] ---------------------------------------- 0.16 1.77 1/1 start [1] [2] 100.00 0.16 1.77 1 main [2] 1.77 0 1/1 a <cycle 1> [5] ---------------------------------------- 1.77 0 1/1 main [2] [3] 91.71 1.77 0 1+5 <cycle 1 as a whole> [3] 1.02 0 3 b <cycle 1> [4] 0.75 0 2 a <cycle 1> [5] 0 0 6/6 c [6] ---------------------------------------- 3 a <cycle 1> [5] [4] 52.85 1.02 0 0 b <cycle 1> [4] 2 a <cycle 1> [5] 0 0 3/6 c [6] ---------------------------------------- 1.77 0 1/1 main [2] 2 b <cycle 1> [4] [5] 38.86 0.75 0 1 a <cycle 1> [5] 3 b <cycle 1> [4] 0 0 3/6 c [6] ---------------------------------------- 0 0 3/6 b <cycle 1> [4] 0 0 3/6 a <cycle 1> [5] [6] 0.00 0 0 6 c [6] ---------------------------------------- |
The self
field of the cycle's primary line is the total time
spent in all the functions of the cycle. It equals the sum of the
self
fields for the individual functions in the cycle, found
in the entry in the subroutine lines for these functions.
The children
fields of the cycle's primary line and subroutine lines
count only subroutines outside the cycle. Even though a
calls
b
, the time spent in those calls to b
is not counted in
a
's children
time. Thus, we do not encounter the problem of
what to do when the time in those calls to b
includes indirect
recursive calls back to a
.
The children
field of a caller-line in the cycle's entry estimates
the amount of time spent in the whole cycle, and its other
subroutines, on the times when that caller called a function in the cycle.
The calls
field in the primary line for the cycle has two numbers:
first, the number of times functions in the cycle were called by functions
outside the cycle; second, the number of times they were called by
functions in the cycle (including times when a function in the cycle calls
itself). This is a generalization of the usual split into non-recursive and
recursive calls.
The calls
field of a subroutine-line for a cycle member in the
cycle's entry says how many time that function was called from functions in
the cycle. The total of all these is the second number in the primary line's
calls
field.
In the individual entry for a function in a cycle, the other functions in
the same cycle can appear as subroutines and as callers. These lines show
how many times each function in the cycle called or was called from each other
function in the cycle. The self
and children
fields in these
lines are blank because of the difficulty of defining meanings for them
when recursion is going on.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gprof
's `-l' option causes the program to perform
line-by-line profiling. In this mode, histogram
samples are assigned not to functions, but to individual
lines of source code. The program usually must be compiled
with a `-g' option, in addition to `-pg', in order
to generate debugging symbols for tracking source code lines.
The flat profile is the most useful output table
in line-by-line mode.
The call graph isn't as useful as normal, since
the current version of gprof
does not propagate
call graph arcs from source code lines to the enclosing function.
The call graph does, however, show each line of code
that called each function, along with a count.
Here is a section of gprof
's output, without line-by-line profiling.
Note that ct_init
accounted for four histogram hits, and
13327 calls to init_block
.
Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls us/call us/call name 30.77 0.13 0.04 6335 6.31 6.31 ct_init Call graph (explanation follows) granularity: each sample hit covers 4 byte(s) for 7.69% of 0.13 seconds index % time self children called name 0.00 0.00 1/13496 name_too_long 0.00 0.00 40/13496 deflate 0.00 0.00 128/13496 deflate_fast 0.00 0.00 13327/13496 ct_init [7] 0.0 0.00 0.00 13496 init_block |
Now let's look at some of gprof
's output from the same program run,
this time with line-by-line profiling enabled. Note that ct_init
's
four histogram hits are broken down into four lines of source code - one hit
occurred on each of lines 349, 351, 382 and 385. In the call graph,
note how
ct_init
's 13327 calls to init_block
are broken down
into one call from line 396, 3071 calls from line 384, 3730 calls
from line 385, and 6525 calls from 387.
Flat profile: Each sample counts as 0.01 seconds. % cumulative self time seconds seconds calls name 7.69 0.10 0.01 ct_init (trees.c:349) 7.69 0.11 0.01 ct_init (trees.c:351) 7.69 0.12 0.01 ct_init (trees.c:382) 7.69 0.13 0.01 ct_init (trees.c:385) Call graph (explanation follows) granularity: each sample hit covers 4 byte(s) for 7.69% of 0.13 seconds % time self children called name 0.00 0.00 1/13496 name_too_long (gzip.c:1440) 0.00 0.00 1/13496 deflate (deflate.c:763) 0.00 0.00 1/13496 ct_init (trees.c:396) 0.00 0.00 2/13496 deflate (deflate.c:727) 0.00 0.00 4/13496 deflate (deflate.c:686) 0.00 0.00 5/13496 deflate (deflate.c:675) 0.00 0.00 12/13496 deflate (deflate.c:679) 0.00 0.00 16/13496 deflate (deflate.c:730) 0.00 0.00 128/13496 deflate_fast (deflate.c:654) 0.00 0.00 3071/13496 ct_init (trees.c:384) 0.00 0.00 3730/13496 ct_init (trees.c:385) 0.00 0.00 6525/13496 ct_init (trees.c:387) [6] 0.0 0.00 0.00 13496 init_block (trees.c:408) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gprof
's `-A' option triggers an annotated source listing,
which lists the program's source code, each function labeled with the
number of times it was called. You may also need to specify the
`-I' option, if gprof
can't find the source code files.
Compiling with `gcc ... -g -pg -a' augments your program
with basic-block counting code, in addition to function counting code.
This enables gprof
to determine how many times each line
of code was executed.
For example, consider the following function, taken from gzip,
with line numbers added:
1 ulg updcrc(s, n) 2 uch *s; 3 unsigned n; 4 { 5 register ulg c; 6 7 static ulg crc = (ulg)0xffffffffL; 8 9 if (s == NULL) { 10 c = 0xffffffffL; 11 } else { 12 c = crc; 13 if (n) do { 14 c = crc_32_tab[...]; 15 } while (--n); 16 } 17 crc = c; 18 return c ^ 0xffffffffL; 19 } |
updcrc
has at least five basic-blocks.
One is the function itself. The
if
statement on line 9 generates two more basic-blocks, one
for each branch of the if
. A fourth basic-block results from
the if
on line 13, and the contents of the do
loop form
the fifth basic-block. The compiler may also generate additional
basic-blocks to handle various special cases.
A program augmented for basic-block counting can be analyzed with
`gprof -l -A'. I also suggest use of the `-x' option,
which ensures that each line of code is labeled at least once.
Here is updcrc
's
annotated source listing for a sample gzip
run:
ulg updcrc(s, n) uch *s; unsigned n; 2 ->{ register ulg c; static ulg crc = (ulg)0xffffffffL; 2 -> if (s == NULL) { 1 -> c = 0xffffffffL; 1 -> } else { 1 -> c = crc; 1 -> if (n) do { 26312 -> c = crc_32_tab[...]; 26312,1,26311 -> } while (--n); } 2 -> crc = c; 2 -> return c ^ 0xffffffffL; 2 ->} |
In this example, the function was called twice, passing once through
each branch of the if
statement. The body of the do
loop was executed a total of 26312 times. Note how the while
statement is annotated. It began execution 26312 times, once for
each iteration through the loop. One of those times (the last time)
it exited, while it branched back to the beginning of the loop 26311 times.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |