Compiler Instrumentation


As the compiler transforms the source code, it can also ‘insert’ additional code into a program. These transformations are called compiler instrumentation. There are many uses of compiler instrumentation, one of the common purposes is to collect the ‘runtime profile’ of a program.

To collect the runtime profile, a compiler would insert ‘counters’ at certain parts of the program and those counters would increment every time the program execution reaches the site of instrumentation.

After the program is finished, the counters can be used to understand the performance profile. The hottest parts of the program are most interesting to performance engineers.

Using Compiler Instrumentation

Compilers can insert ‘counters’ at interesting program points to collect runtime profiles. The code is instrumented by passing -fprofile-generate to the compiler.

$ gcc -O2 -fprofile-generate=/path/to/outputfile test.c -o a.out

Because of instrumentation, the application itself will then log events/counters that can be used by the compiler during the next compilation. After the program exits, it will create a file in the /path/to/outputfile/ directory with .gcda extension. Then recompiling the application with -fprofile-use=/path/to/outputfile will result in an optimised program.

$ gcc -O2 -fprofile-use=/path/to/outputfile test.c -o b.out

b.out is optimised with profile information. The compiler often optimises the code layout, function inlining, and loops with profile information. It is common to see performance improvements of over 10% with PGO (Profile-Guided Optimisation).