2

How do I produce a graphical code profile report for C++ code compiled with Clang LLVM?

  • What command-line options to I pass to clang++ to instruct it to gather profiling data when the code is executed?

  • Into which file(s) is the gathered profiling data stored?

  • What are the post-processing steps to convert the collected profile data into a graphical report that shows how often each function is called, what percentage of time is spent in each function, and from which functions each function is called (similar to https://s3-us-west-2.amazonaws.com/brunorijsman-public/example-rift-python-code-profile.png)?

I have full control over the C++ source code and Makefile.

It has to be LLVM clang++ (GNU g++ is not an option for me). Xcode is also not an option for me.

Bruno Rijsman
  • 3,715
  • 4
  • 31
  • 61
  • Are you looking for something like [vcperf](https://github.com/microsoft/vcperf) for Linux (also discussed in some depth on [this CppCast episode](https://cppcast.com/cpp-build-insights/))? IncrediBuild, which is available for Linux under a free trial, produces a similar graph, but not to the same level of granularity (it covers file build times and shows parallel bottlenecks, not granular metrics like template instantiation time and header processing time). – metal Apr 01 '20 at 14:53
  • @metal It seems that vcperf and incredibuild provide a report on where the time is spent BUILDING my code. If so that is not what I am looking for. I would like to find out where the time is spent EXECUTING my code. – Bruno Rijsman Apr 01 '20 at 18:51
  • Oh, then it probably doesn't need to matter that it's clang or gcc. You might use [gprof](https://users.cs.duke.edu/~ola/courses/programming/gprof.html), [callgrind](https://web.stanford.edu/class/archive/cs/cs107/cs107.1174/guide_callgrind.html), and/or [kcachegrind](https://kcachegrind.github.io/). [Here's a video](https://www.youtube.com/watch?v=2EWejmkKlxs) from CppCon 2017 on profiling and optimizing. See Chandler Caruth's other talks for more. – metal Apr 01 '20 at 19:04
  • @metal Ah, I wasn't aware that it doesn't matter whether it is gcc or clang. I assumed clang had its own toolchain for profiling, different from gcc's toolchain. Let me try gprof or your other suggestions. Thanks! – Bruno Rijsman Apr 01 '20 at 20:33

2 Answers2

6

Clang supports a couple of different code coverage implementations (which also output how often a line has been executed) such as Source-Based Code Coverage and a gcov-compatible one. Open source tools seems to have better support for gcov output in general, so I would recommend that route.

What command-line options to I pass to clang++ to instruct it to gather profiling data when the code is executed?

  • For Source-Based Code Coverage: According to llvm-cov, the correct flags for gathering profiling data when is -fprofile-instr-generate -fcoverage-mapping when compiling and -fprofile-instr-generate when linking.
  • For the gcov compatible output: -fprofile-arcs -ftest-coverage

Into which file(s) is the gathered profiling data stored?

  • For Source-Based Code Coverage: After you run the program compile and linked with the flags above, the coverage data is stored in default.profraw in your current working directory. The profiling data file name can be changed by recompiling with -fprofile-instr-generate=filename or by setting the environment variable LLVM_PROFILE_FILE before running the executable.
  • For gcov compatible output: After you run the program you will get *.gcda and *.gcno files.

What are the post-processing steps to convert the collected profile data into a graphical report that shows how often each function is called, what percentage of time is spent in each function

  • For Source-Based Code Coverage:

    1. Index your .profraw file into a .profdata file: llvm-profdata merge -o default.profdata -sparse=true default.profraw
    2. Either use llvm-cov show --instr-profile default.profdata ./your_program to view the coverage in the terminal or use llvm-cov export ./your_program --instr-profile default.profdata > out.json to convert your profiling data to JSON and find/create a program to generate a report for you.
  • For gcov-compatible output:

    1. Use lcov or gcovr to generate HTML output. This lets you easily view line and branch coverage for each file. I tend to use gcovr since it is a simple pip install gcovr away if you don't have it installed. Then the usage would be gcovr --gcov-executable "llvm-cov gcov" -r . --html --html-details -o out.html.

and from which functions each function is called (similar to https://s3-us-west-2.amazonaws.com/brunorijsman-public/example-rift-python-code-profile.png)?

For this type of information I would try to have a look at Callgrind and KCacheGrind. I have not found any tool which can generate this type of information given *.profdata or *.gcda files.

Joskar
  • 600
  • 5
  • 12
  • Awarding bounty before it expires, although I have not yet the opportunity to try out all the suggestion in this answer (it looks promising thus far). – Bruno Rijsman Apr 03 '20 at 18:18
  • @Joskar Can you kindly guide how to use the above commands if I want to build project using CMake? I have asked a [question](https://stackoverflow.com/questions/73922182/how-to-do-profiling-using-clang-compiler-and-cmake) here. Maybe helpful to understand my query. – user10634362 Oct 03 '22 at 09:58
0

As aforementioned, gprof is one profiling tool that you can use. There's a problem however,it only counts CPU-time-in-process, it basically can't see I/O calls. It's also confused by recursion. Callgrind also shares similar problems, KCacheGrind uses Valgrind which actually interprets all the code. At the end of the day however, these are the options, personally, for small scale I would go with gprof simply due to its usability and documentation.

Gagan Bhat
  • 352
  • 3
  • 11