From 2cee0b6c1225d96cfd46274071a6f158c411cae7 Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Tue, 23 Jan 2024 00:42:53 +0100 Subject: callgrind: initial notes --- src/SUMMARY.md | 3 +- src/trace_profile/README.md | 3 +- src/trace_profile/callgrind.md | 76 +++++++++++++++++++++++++++++++ src/trace_profile/callgrind/Makefile | 14 ++++++ src/trace_profile/callgrind/cg_example.cc | 36 +++++++++++++++ 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 src/trace_profile/callgrind.md create mode 100644 src/trace_profile/callgrind/Makefile create mode 100644 src/trace_profile/callgrind/cg_example.cc diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 0073de0..d0e83ff 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -31,11 +31,12 @@ - [pstack](./monitor/pstack.md) - [Trace and Profile](./trace_profile/README.md) + - [time](./trace_profile/time.md) - [strace](./trace_profile/strace.md) - [ltrace](./trace_profile/ltrace.md) - [perf](./trace_profile/perf.md) - [OProfile](./trace_profile/oprofile.md) - - [time](./trace_profile/time.md) + - [callgrind](./trace_profile/callgrind.md) - [Binary](./binary/README.md) - [od](./binary/od.md) diff --git a/src/trace_profile/README.md b/src/trace_profile/README.md index 140d496..a0168b8 100644 --- a/src/trace_profile/README.md +++ b/src/trace_profile/README.md @@ -1,7 +1,8 @@ # Trace and Profile +- [time](./time.md) - [strace](./strace.md) - [ltrace](./ltrace.md) - [perf](./perf.md) - [OProfile](./oprofile.md) -- [time](./time.md) +- [callgrind](./callgrind.md) diff --git a/src/trace_profile/callgrind.md b/src/trace_profile/callgrind.md new file mode 100644 index 0000000..1336a9e --- /dev/null +++ b/src/trace_profile/callgrind.md @@ -0,0 +1,76 @@ +# callgrind + +Callgrind is a tracing profiler to record the function call history of a target +program. It is part of the [valgrind][callgrind] tool suite. + +Profiling data is collected by instrumentation rather than sampling of the +target program. + +Callgrind does not capture the actual time spent in a function but computes the +cost of a function based on the instructions fetched (`Ir = Instruction read`). +Therefore effects like slow IO are not reflected, which should be kept in mind +when analyzing callgrind results. + +By default the profiler data is dumped when the target process is terminating, +but [callgrind_control] allows for interactive control of callgrind. +```bash +# Run a program under callgrind. +valgrind --tool=callgrind -- + +# Interactive control of callgrind. +callgrind_control [opts] + opts: + -b ............. show current backtrace + -e ............. show current event counters + -s ............. show current stats + --dump[=file] .. dump current collection + -i=on|off ...... turn instrumentation on|off +``` + +Results can be analyzed by using one of the following tools +- [callgrind_annotate] (cli) +- [kcachegrind] (ui) + +The following is a collection of frequently used callgrind options. +```bash +valgrind --tool=callgrind [opts] -- + opts: + --callgrind-out-file= .... output file, rather than callgrind.out. + --dump-instr= .......... annotation on instrucion level, + allows for asm annotations + + --instr-atstart= ....... control if instrumentation is enabled from + beginning of the program + + --separate-threads= .... create separate output files per thread, + appends - to the output file +``` + +## Profile specific part of the target +Programmatically enable/disable instrumentation using the macros defined in +the callgrind header. +```c +#include + +int main() { + // init .. + + CALLGRIND_START_INSTRUMENTATION; + compute(); + CALLGRIND_STOP_INSTRUMENTATION; + + // shutdown .. +} +``` +> In this case, callgrind should be launched with `--instr-atstart=no`. + +Alternatively instrumentation can be controlled with `callgrind_control -i +on/off`. + +The files [cg_example.cc](callgrind/cg_example.cc) and +[Makefile](callgrind/Makefile) provide a full example. + +[callgrind]: https://valgrind.org/docs/manual/cl-manual.html +[callgrind_annotate]: https://valgrind.org/docs/manual/cl-manual.html#cl-manual.callgrind_annotate-options +[callgrind_control]: https://valgrind.org/docs/manual/cl-manual.html#cl-manual.callgrind_control-options +[kcachegrind]: https://kcachegrind.github.io/html/Home.html diff --git a/src/trace_profile/callgrind/Makefile b/src/trace_profile/callgrind/Makefile new file mode 100644 index 0000000..0da099c --- /dev/null +++ b/src/trace_profile/callgrind/Makefile @@ -0,0 +1,14 @@ +prof: cg_example + valgrind --tool=callgrind --dump-instr=yes --instr-atstart=no -- ./cg_example + +prof-cache: cg_example + valgrind --tool=callgrind --dump-instr=yes --instr-atstart=no --cache-sim=yes -- ./cg_example + +show: + callgrind_annotate + +cg_example: cg_example.cc + clang++ -o cg_example -Wall -Wextra -O2 -g -fno-inline cg_example.cc -lpthread + +clean: + $(RM) callgrind.* cg_example diff --git a/src/trace_profile/callgrind/cg_example.cc b/src/trace_profile/callgrind/cg_example.cc new file mode 100644 index 0000000..d143790 --- /dev/null +++ b/src/trace_profile/callgrind/cg_example.cc @@ -0,0 +1,36 @@ +#include +#include + +#include + +struct cnt { + volatile int a; + volatile int b; +}; + +void inc_a(cnt &c) { c.a++; } +void inc_b(cnt &c) { c.b++; } + +int main() { + cnt C{0, 0}; + + CALLGRIND_START_INSTRUMENTATION; + + std::thread T1([&C]() { + for (int i = 0; i < 20000000; ++i) { + inc_a(C); + } + }); + std::thread T2([&C]() { + for (int i = 0; i < 10000000; ++i) { + inc_b(C); + } + }); + T1.join(); + T2.join(); + + CALLGRIND_STOP_INSTRUMENTATION; + + printf("%d %d\n", C.a, C.b); + return 0; +} -- cgit v1.2.3