GCC

GCC Profiling

Article by:
Date Published:
Last Modified:
Note
This article assumes you are using a Debian-based Linux machine (e.g. Ubuntu).

Overview

To use profiling, the program must be compiled and linked with the -qg profiling option:

We will use an called profiling_test.c (full code can be found at https://github.com/gbmhunter/BlogAssets/tree/master/Programming/ProfilingGprof):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

int fibonacci(int n) {
    if(n == 0)
        return 0;
    else if(n == 1)
        return 1;
    else
        return(fibonacci(n-1) + fibonacci(n-2));
} 

int loop100M() {
    int val = 0;
    for(int i = 0; i < 100000000; i++) {
    if(i % 10 == 0)
        val++;
    else if(i % 3)
        val--;
    }
    return val;
}

int main (void) {  
    printf("Fibonacci value = %u\n", fibonacci(40));          
    printf("Loop value = %u\n", loop100M());

    return 0;
}

We will then compile it with the command:

1
$ gcc -pg profiling_test.c -o profiling_test

This creates what is called an instrumented executable. It contains additional code which records the time spent in each function.

Warning
If gprof does not appear to produce any output, it may be because of a bug in GCC versions 5 and 6. As a workout, provide the additional flag -no-pie to compilation and linking. Make sure there is only one hyphen at the start of the argument (NOT –no-pie).

When run, the program will produce a file gmon.out in the same directory as it is run. You can pass your program to gprof to display the profiling results:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ gprof ./profiling_test
Flat profile:

Each sample counts as 0.01 seconds.
    %   cumulative   self              self     total           
    time   seconds   seconds    calls  ms/call  ms/call  name    
    60.96      0.68     0.68        1   676.63   676.63  fibonacci
    31.84      1.03     0.35        1   353.47   353.47  loop100M
    8.19      1.12     0.09                             frame_dummy
...

You can see above that approximately 60% of the time was spent calculating the Fibonacci sequence, while 30% was spent looping 100 million times. If this was a real life scenario, you could now start to optimise your code!

If you find text hard to analyze, see the gprof2dot section below on how to create a visualization of the above results.

The above command will write the profiling results to the terminal. Instead, if you wish to write the results to a file, use the following command:

1
$ gprof profiling_test > profiling_results.txt

Clean Exiting

gmon.out is only written to if your C/C++ program exits cleanly, that is, it either calls exit() or returns from main().

Here is the relevant info from the gprof manual:

The profiled program must call "exit"(2) or return normally for the profiling information to be saved in the gmon.out file.

Your program doesn’t count as a clean exit if it is running in a Linux terminal and Ctrl-C is pressed! However, there is a way to fix this, by catching the Ctrl-C signal and writing to the file before exiting…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>

void SigIntHandler(int sig) {
    fprintf(stderr, "Exiting on SIGUSR1\n");
    void (*_mcleanup)(void);
    _mcleanup = (void (*)(void)) dlsym(RTLD_DEFAULT, "_mcleanup");
    if (_mcleanup == NULL)
        fprintf(stderr, "Unable to find gprof exit hook\n");
    else _mcleanup();
    _exit(0);
}

int main() {
    signal(SIGINT, SigIntHandler);

    ... code that does not return here
}
Note
You must compile and link with the -ldl option for dlsym to be found.

gprof2dot

gprof2dot is a tool that can create a visualization of the gprof output. TO install gprof2dot:

1
$ pip install gprof2dot

To install graphviz (which is needed if you are going to make “dot” graphs like below):

1
$ sudo apt install graphviz

To create a dot graph image:

1
$ gprof2dot ./profiling.txt | dot -Tpng -o profiling.png

This created the below image for the example code above:

A profile of the execution time of the example code. Graph was created using gprof and the gprof2dot tool.

A profile of the execution time of the example code. Graph was created using gprof and the gprof2dot tool.


Authors

Geoffrey Hunter

Dude making stuff.

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License .

Related Content:

Tags

comments powered by Disqus
Page contents: