From 6a20478abb517a8c6c046a1ff640fa02d118aa88 Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sun, 25 Apr 2021 12:23:52 -0300
Subject: [PATCH] perf-test: add option to run perf

Although the generation of perf data is not as slow as valgrind, it
seems simplest to re-use the machinery already there to save the logs
in a timestamped subdirectory.
---
 performance-test/README           | 16 ++++++++++++++-
 performance-test/perf-test-lib.sh | 34 +++++++++++++++++++++++++++----
 2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/performance-test/README b/performance-test/README
index fbc61028..59b37b1b 100644
--- a/performance-test/README
+++ b/performance-test/README
@@ -16,6 +16,7 @@ In addition to having notmuch, you need:
 - xz. Some speedup can be gotten by installing "pixz", but this is
   probably only worthwhile if you are debugging the tests.
 - valgrind (for the memory tests)
+- perf (optional, for more fine-grained timing)
 
 Getting set up to run tests:
 ----------------------------
@@ -56,11 +57,24 @@ supports the following arguments
 
 --small / --medium / --large	Choose corpus size.
 --debug				Enable debugging. In particular don't delete
-				temporary directories.
+                                temporary directories.
+--perf                          Run perf record in place of /usr/bin/time. Perf output can be
+                                found in a log directory.
+--call-graph {fp,lbr,dwarf}     Call graph option for perf record. Default is 'lbr'.
 
 When using the make targets, you can pass arguments to all test
 scripts by defining the make variable OPTIONS.
 
+Log Directory
+-------------
+
+The memory tests, and the time tests when option '--perf' is given
+save their output in a directory named as follows
+
+     log.$test_name-$corpus_size-$timestamp
+
+These directories are removed by "make clean".
+
 Writing tests
 -------------
 
diff --git a/performance-test/perf-test-lib.sh b/performance-test/perf-test-lib.sh
index b70288cc..e7c502b6 100644
--- a/performance-test/perf-test-lib.sh
+++ b/performance-test/perf-test-lib.sh
@@ -1,6 +1,9 @@
 . $(dirname "$0")/version.sh || exit 1
 
+debug=""
 corpus_size=large
+perf_callgraph=lbr
+use_perf=0
 
 while test "$#" -ne 0
 do
@@ -9,6 +12,15 @@ do
 		debug=t;
 		shift
 		;;
+	-p|--perf)
+		use_perf=1;
+		shift
+		;;
+	-c|--call-graph)
+		shift
+		perf_callgraph=$1
+		shift
+		;;
 	-s|--small)
 		corpus_size=small;
 		shift
@@ -127,10 +139,20 @@ notmuch_new_with_cache ()
     fi
 }
 
+make_log_dir () {
+    local timestamp=$(date +%Y%m%dT%H%M%S)
+    log_dir=${TEST_DIRECTORY}/log.$(basename $0)-$corpus_size-${timestamp}
+    mkdir -p "${log_dir}"
+}
+
 time_start ()
 {
     add_email_corpus
 
+    if [[ "$use_perf" = 1 ]]; then
+	make_log_dir
+    fi
+
     print_header
 
     notmuch_new_with_cache time_run
@@ -140,9 +162,7 @@ memory_start ()
 {
     add_email_corpus
 
-    local timestamp=$(date +%Y%m%dT%H%M%S)
-    log_dir="${TEST_DIRECTORY}/log.$(basename $0)-$corpus_size-${timestamp}"
-    mkdir -p ${log_dir}
+    make_log_dir
 
     notmuch_new_with_cache memory_run
 }
@@ -193,7 +213,13 @@ time_run ()
     printf "  %-22s" "$1"
     test_count=$(($test_count+1))
     if test "$verbose" != "t"; then exec 4>test.output 3>&4; fi
-    if ! eval >&3 "/usr/bin/time -f '%e\t%U\t%S\t%M\t%I/%O' $2" ; then
+    if [[ "$use_perf" = 1 ]]; then
+	command_str="perf record --call-graph=${perf_callgraph} -o ${log_dir}/${test_count}.perf $2"
+    else
+	command_str="/usr/bin/time -f '%e\t%U\t%S\t%M\t%I/%O' $2"
+    fi
+
+    if ! eval >&3 "$command_str" ; then
 	test_failure=$(($test_failure + 1))
 	return 1
     fi
-- 
2.45.2