Profiling C++ Code: Finding Bottlenecks for Beginners

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why is it important to profile C++ code?

\n

C++ is one of the fastest programming languages, but even in it you can write slow code. Developers often spend hours optimizing the wrong parts of a program based on intuition. Profiling is a scientific approach to optimization: you measure where the program spends the most time and purposefully improve those areas.

\n

For beginner C++ programmers, profiling may seem complex, but basic tools can be mastered in one evening. In this article, we will cover three popular tools: gprof, perf, and Valgrind, and learn how to interpret their results.

\n\n

What is profiling and what methods exist?

\n

Profiling is the collection of data about a program's operation during its execution. There are two main approaches:

\n
    \n
  • Instrumenting profiling — special "probes" are added to the program code (e.g., gprof). Downside: it slows down program execution.
  • \n
  • Sampling profiling — at regular intervals, it "peeks" into the program and records which function is currently executing (e.g., perf). It barely slows down the program.
  • \n
\n

There are also tools for finding memory leaks (Valgrind) and cache analysis. To start, it's enough to master gprof and perf.

\n\n

Tool 1: gprof — the classic profiler

\n

gprof is a built-in profiler for GCC. It works in two stages: data collection and analysis.

\n

How to use gprof

\n

First, compile the program with the -pg flag:

\n
g++ -pg -o my_program my_program.cpp
\n

Run the program:

\n
./my_program
\n

After execution, a file called gmon.out will appear. Now run gprof:

\n
gprof my_program gmon.out > report.txt
\n

Open report.txt and look at the table:

\n
Flat profile:\nEach sample counts as 0.01 seconds.\n  %   cumulative   self              self     total\n time   seconds   seconds    calls  ms/call  ms/call  name\n 60.00      0.06     0.06    10000     0.01     0.01  slow_function\n 30.00      0.09     0.03     5000     0.01     0.02  medium_function\n 10.00      0.10     0.01        1    10.00    10.00  main
\n

The % time column shows what percentage of time the function took. In our example, slow_function is the main candidate for optimization.

\n

Tip: For small programs, gprof works great. For large projects, it can give inaccurate data due to compiler optimizations.

\n\n

Tool 2: perf — a powerful sampler for Linux

\n

perf is a profiler built into the Linux kernel. It works using the sampling method and barely slows down the program. It is ideal for production systems.

\n

Basic usage of perf

\n

Compile the program with debug symbols (the -g flag):

\n
g++ -g -o my_program my_program.cpp
\n

Start profiling:

\n
perf record ./my_program
\n

After the program finishes, view the report:

\n
perf report
\n

You will see an interactive interface. By clicking on a function, you can see which lines of code were executed most often. Example output:

\n
Samples: 1K of event 'cycles'\nEvent count (approx.): 250000000\nOverhead  Command      Shared Object     Symbol\n  45.32%  my_program   my_program        [.] slow_function\n  30.15%  my_program   my_program        [.] medium_function\n  12.50%  my_program   libc-2.31.so      [.] malloc\n   8.03%  my_program   my_program        [.] main
\n

Important: perf requires root privileges to collect kernel

Blogs

Book Recommendations