[PATCH v3 4/5] perf test: Add a runs-per-test flag

From: Ian Rogers
Date: Thu Jan 09 2025 - 13:42:06 EST


To detect flakes it is useful to run tests more than once. Add a
runs-per-test flag that will run each test multiple times. Example
output:

```
$ perf test -r 3 lbr -v
122: perf record LBR tests : Ok
122: perf record LBR tests : Ok
122: perf record LBR tests : Ok
```

Update the documentation for the runs-per-test option.

Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/Documentation/perf-test.txt | 9 ++++++++-
tools/perf/tests/builtin-test.c | 28 ++++++++++++++++----------
2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index 8f8a3c367570..85f868c324ff 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -33,7 +33,14 @@ OPTIONS

-S::
--sequential::
- Run tests one after the other, this is the default mode.
+ Run all tests one after the other. By default "exclusive"
+ tests are run sequentially, but other tests are run in
+ parallel to speed execution.
+
+-r::
+--runs-per-test::
+ Run each test the given number of times, by default once. This
+ option can be useful to determine if a test is flaky.

-F::
--dont-fork::
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 887f735da900..729740c1e5e5 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -42,6 +42,8 @@
static bool dont_fork;
/* Fork the tests in parallel and wait for their completion. */
static bool sequential;
+/* Number of times each test is run. */
+static unsigned int runs_per_test = 1;
const char *dso_to_test;
const char *test_objdump_path = "objdump";

@@ -485,7 +487,7 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[],
len = strlen(test_description(*t, i));
if (width < len)
width = len;
- num_tests++;
+ num_tests += runs_per_test;
}
}
child_tests = calloc(num_tests, sizeof(*child_tests));
@@ -549,16 +551,18 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[],
continue;
}

- test_suite__for_each_test_case(*t, curr_test_case) {
- if (!perf_test__matches(test_description(*t, curr_test_case),
- curr_suite, argc, argv))
- continue;
-
- err = start_test(*t, curr_suite, curr_test_case,
- &child_tests[child_test_num++],
- width, pass);
- if (err)
- goto err_out;
+ for (unsigned int run = 0; run < runs_per_test; run++) {
+ test_suite__for_each_test_case(*t, curr_test_case) {
+ if (!perf_test__matches(test_description(*t, curr_test_case),
+ curr_suite, argc, argv))
+ continue;
+
+ err = start_test(*t, curr_suite, curr_test_case,
+ &child_tests[child_test_num++],
+ width, pass);
+ if (err)
+ goto err_out;
+ }
}
}
if (!sequential) {
@@ -698,6 +702,8 @@ int cmd_test(int argc, const char **argv)
"Do not fork for testcase"),
OPT_BOOLEAN('S', "sequential", &sequential,
"Run the tests one after another rather than in parallel"),
+ OPT_UINTEGER('r', "runs-per-test", &runs_per_test,
+ "Run each test the given number of times, default 1"),
OPT_STRING('w', "workload", &workload, "work", "workload to run for testing, use '--list-workloads' to list the available ones."),
OPT_BOOLEAN(0, "list-workloads", &list_workloads, "List the available builtin workloads to use with -w/--workload"),
OPT_STRING(0, "dso", &dso_to_test, "dso", "dso to test"),
--
2.47.1.613.gc27f4b7a9f-goog