Profiling C++ on Linux

Profiling is an essential practice for software developers: it helps in identifying the parts of the program which consume most of resources, whether it is CPU time or memory. Consequently, profiling is crucial for deciding which parts of the source code should receive attention and for optimizing source code to run more efficiently. This is especially important if you work on performance-critical applications in scientific computing.

Several Profiling tools are available on Linux for profiling applications written in C++. Here, we will focus on two main toolsets: on the one hand, using GProf, which is a terminal-based profiling tool, and on the other hand, using Valgrind together with Callgrind and KCachegrind, which includes a GUI.

I will only address tools for a Linux/Unix environment. There are other tools available on Windows.

Profiling using Valgrind, Callgrind, and KCachegrind

  1. Valgrind is a versatile software suite. It consists of various components for debugging and profiling software. The Callgrind component facilitates profiling.
  2. We must first compile the application with debugging information. When using GCC for the compilation, we achieved this by using the -g option. The compiler will then embed debugging information into the executable.
  3. After compiling the program, we employ Valgrind's Callgrind tool to generate profiling data; The following command tells Valgrind to run our program using the Callgrind tool.
    
                        valgrind --tool=callgrind [callgrind options] our_program [program options]
                        
    We can specify various options for Callgrind to control its behavior, as well as pass arguments to our program as needed.
  4. Callgrind will generate a profiling data file named callgrind.out.[pid], where [pid] is the process ID of our program. This file contains detailed profiling information, to be used by other programs.
  5. We analyze the data with KCachegrind, which is a graphical user interface that presents the profiling information in a more accessible manner. We open the generated file in KCachegrind with the following command:
    
                            kcachegrind callgrind.out.[pid]
                        
  6. KCachegrind is a GUI tool to explore the data in the data file. It can visualize the call graph, identify how often functions have been called, and how much time was spent in each function.

Profiling using GProf

  1. Another tool at our disposal is GProf, the GNU Profiler, which is a profiler that comes with the GNU Binutils suite. This is not a graphical tool by itself, but it generates a flat profile and call graph analysis of our program. This analysis provides insights into how often functions are called and how much time is spent in each function.
  2. To use GProf, we need to compile our program with the -pg option, which enables profiling information to be included in the executable. The -pg must be part of both the compilation and the linking process, which is typically ensured by GCC.
  3. Running our program will now automatically create a file named gmon.out, which contains the profiling data.
  4. We can then analyze this data with GProf by executing the following command:
    
                        gprof our_program gmon.out
                        
  5. This command will output the profiling analysis to the terminal. Here, we can see the time spent in each function and the call relationships between functions. Note that GProf does not offer a GUI but is only text-based. Its main application is as a tool that facilitates post-processing by scripts. One strong advantage over GUI tools the GProf output can easily be incorporated in an automated profiling workflow.
  6. Further information can be found in the official documentation: http://sourceware.org/binutils/docs/gprof/