aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/trace_profile
diff options
context:
space:
mode:
authorJohannes Stoelp <johannes.stoelp@gmail.com>2024-01-23 00:42:53 +0100
committerJohannes Stoelp <johannes.stoelp@gmail.com>2024-01-23 00:42:53 +0100
commit2cee0b6c1225d96cfd46274071a6f158c411cae7 (patch)
treea52b514ef7cbff80b3caa9f2879e85fb911ee9cc /src/trace_profile
parent42c4782598dae5728539b24f83ebafc3e33b7448 (diff)
downloadnotes-2cee0b6c1225d96cfd46274071a6f158c411cae7.tar.gz
notes-2cee0b6c1225d96cfd46274071a6f158c411cae7.zip
callgrind: initial notes
Diffstat (limited to 'src/trace_profile')
-rw-r--r--src/trace_profile/README.md3
-rw-r--r--src/trace_profile/callgrind.md76
-rw-r--r--src/trace_profile/callgrind/Makefile14
-rw-r--r--src/trace_profile/callgrind/cg_example.cc36
4 files changed, 128 insertions, 1 deletions
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 -- <prog>
+
+# 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] -- <prog>
+ opts:
+ --callgrind-out-file=<file> .... output file, rather than callgrind.out.<pid>
+ --dump-instr=<yes|no> .......... annotation on instrucion level,
+ allows for asm annotations
+
+ --instr-atstart=<yes|no> ....... control if instrumentation is enabled from
+ beginning of the program
+
+ --separate-threads=<yes|no> .... create separate output files per thread,
+ appends -<thread_id> to the output file
+```
+
+## Profile specific part of the target
+Programmatically enable/disable instrumentation using the macros defined in
+the callgrind header.
+```c
+#include <valgrind/callgrind.h>
+
+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 <cstdio>
+#include <thread>
+
+#include <valgrind/callgrind.h>
+
+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;
+}