Skip to content

Latest commit

 

History

History
54 lines (33 loc) · 4.2 KB

File metadata and controls

54 lines (33 loc) · 4.2 KB

HOWTO Profile Compiled Code

By Michael Hahsler

Looks like you want to improve the runtime of your code. Before you resort to a profiler you should:

  • Turn on compiler optimization. Compilers use code optimization (GCC optimizations). In VS Code, compile the code using in the bottom bar CMake:[Release] (i.e., with speed optimization) instead of CMake: [Debug] (optimizer disabled).
  • Use appropriate data structures and algorithms. Determine what you need (fast lookup or fast insertion) and then choose each data structure based on the Big-O notation and experiments. It is highly recommended to use standard library implementations.
  • Copying objects. Assigning objects happen in many algorithms. Assigning larger objects by copying is expensive. Make sure you implement move semantics for these objects.
  • Avoid recursion and nested loops. Recursions can be replaced by iteration. Often, better algorithms can be used to avoid nested loops.

Profiling Software

Profiling Software measures the space (memory) or time used by a program, the usage of particular instructions, or the frequency and duration of function calls. Most commonly, profiling information serves to aid program optimization by pointing the developer to the part of the code that is the slowest or consumes the most memory.

Several open-source and commercial profilers are available (see List of performance analysis tools). Here I use callgrind and KCachegrind. Alternatives are perf for Linux and WSL2, and Dtrace for MacOS.

Details on callgrind can be found in the callgrind manual. callgrind records each function call and how many machine code instructions were fetched. It can also calculate approximate run time by translating the instructions into cycle estimates.

How to use callgrind/KCachgrind to Profile Runtime

Installation: You need to install valgrind and KCachgrind on your machine (Linux, WSL2; not available for Mac). If you use a remote Linux servers (e.g., SMU's genuse machines) or WSL2, then you need to install the X server software on your computer (e.g., Xming or XQuarz) and start the X server. Now you log into the server using ssh -X username@server in your shell. This will forward the window of kcachegrind from the server to your local desktop.

  1. Compile your program with optimization on and debug information included (in VSCode: [RelWithDebInfo])

  2. Run your executable with valgrind:

    valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --collect-jumps=yes ./<executable> [args...]
    
  3. This will produce a callgrind.out.xxxxx file. Open the file with:

    kcachegrind callgrind.out.xxxxx
    

    Here is short document on Profiling with Valgrind and visualization with KCachegrind.

  4. Find the file/class you are interested in (e.g., main.cpp), click on the function below and choose Call Graph in the bottom right window. You should now see what gets called, how often, and how long it takes (in % of the caller). By default only calls that take long are shown. You can change his by right-click on the graph Graph > Min. Node Cost.

  5. Identify the functions that takes the most time and are called often. Optimize the code (loops, used algorithms, and data structure) there and profile again to se if and by how much you have improved the runtime (this can be judged by the number of instructions fetched).

License

CC BY-SA 4.0

All code and documents in this repository are provided under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License.