Add a 'ratio' mode to RCU benchmark. This mode helps investigate performance effects on the ratio between selected two parameters. The command is defined as:
ratio <gp_type> <total> <param1_range> <param1_name> <param2_name> <total> is the sum of <param1> and <param2>. <param1_range> specifies the range of param1's values, and thus param2's values can be calculated as 'total-param1'. Example usage: $ ./perf bench sync rcu ratio sync 10 0:10:3 nreaders nwriters \# Running 'sync/rcu' benchmark: Running experiment with options: nreaders=0 nwriters=10 Experiment finished. Average grace-period duration: 16494.413 microseconds Minimum grace-period duration: 7994.842 50th percentile grace-period duration: 17999.439 90th percentile grace-period duration: 18001.923 99th percentile grace-period duration: 23999.068 Maximum grace-period duration: 24000.441 Cooling down (3s).. Running experiment with options: nreaders=3 nwriters=7 Experiment finished. Average grace-period duration: 140018.793 microseconds Minimum grace-period duration: 11987.02 50th percentile grace-period duration: 120999.879 90th percentile grace-period duration: 218000.011 99th percentile grace-period duration: 218006.372 Maximum grace-period duration: 219002.024 Cooling down (3s).. Running experiment with options: nreaders=6 nwriters=4 Experiment finished. Average grace-period duration: 210481.539 microseconds Minimum grace-period duration: 5999.579 50th percentile grace-period duration: 217999.902 90th percentile grace-period duration: 218000.529 99th percentile grace-period duration: 218998.809 Maximum grace-period duration: 219000.652 Cooling down (3s).. Running experiment with options: nreaders=9 nwriters=1 Experiment finished. Average grace-period duration: 210782.119 microseconds Minimum grace-period duration: 89997.154 50th percentile grace-period duration: 217999.829 90th percentile grace-period duration: 218001.299 99th percentile grace-period duration: 219003.072 Maximum grace-period duration: 324116.763 Signed-off-by: Yuzhuo Jing <[email protected]> --- tools/perf/bench/sync-rcu.c | 74 +++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/tools/perf/bench/sync-rcu.c b/tools/perf/bench/sync-rcu.c index 921520a645ae..73142fd5be21 100644 --- a/tools/perf/bench/sync-rcu.c +++ b/tools/perf/bench/sync-rcu.c @@ -55,6 +55,7 @@ static const char *const bench_rcu_usage[] = { "perf bench sync rcu [options..] [-- <command>..]", "perf bench sync rcu [options..] once <gp_type> [<param=value>..] [-- <command>..]", "perf bench sync rcu [options..] range <gp_type> [<param=range>..] [-- <command>..]", + "perf bench sync rcu [options..] ratio <gp_type> <total> <param1_range> <param1_name> <param2_name> [<param=value>..] [-- <command>..]", "", " <gp_type>: The type of grace period to use: sync, async, exp (expedited)", " This sets the gp_exp or gp_async kernel module parameters.", @@ -83,12 +84,17 @@ static const char *const bench_rcu_usage[] = { " If a parameter does not specify end, or start=end, it behaves", " the same as 'once' mode. The range parameter types are validated", " agains `modinfo rcuscale` to ensure they are integer.", + " ratio: Run benchmark that changes the ratio between two parameters.", + " <total> specifies the sum of param1 and param2, and <param1_range>", + " is the range of param1 values. param2 is calculated by total-param1.", + " Additional non-range parameters may also be specified.", "", "Examples:", " perf bench sync rcu --hist once exp nreaders=1 nwriters=1 writer_cpu_offset=1", " perf bench sync rcu once", " perf bench sync rcu once sync nreaders=1 nwriters=1 writer_cpu_offset=1", " perf bench sync rcu range exp nreaders=1:2 nwriters=1 writer_cpu_offset=0:2", + " perf bench sync rcu ratio sync 10 0:10:3 nreaders nwriters", "", " perf bench sync rcu once sync nreaders=1 nwriters=1 writer_cpu_offset=1 -- \\", " perf stat -e ipi:ipi_send_cpu,rcu:rcu_grace_period \\", @@ -1194,6 +1200,72 @@ static void test_range(int argc, const char *argv[]) test_range_recursive(0, &modprobe_cmd); } +/* + * Test ratio. Use loop on two range options. + * + * Does not allow ranges for other options. + * + * Example: + * perf bench rcu ratio sync 10 1:10:2 nreaders nwriters + * will run the following experiments: + * nreaders=1, nwriters=9 + * nreaders=2, nwriters=8 + * nreaders=3, nwriters=7 + * ... + * nreaders=9, nwriters=1 + */ +static void test_ratio(int argc, const char *argv[]) +{ + MODPROBE_CMD_INIT; + + int total; + struct range option1_range; + const char *option1_name; + const char *option2_name; + + if (argc < 4) + usage_with_options(bench_rcu_usage, bench_rcu_options); + + total = parse_int(argv[0]); + parse_range(&option1_range, argv[1]); + option1_name = argv[2]; + option2_name = argv[3]; + + check_param_name(option1_name); + check_param_name(option2_name); + + if (total < option1_range.start || total < option1_range.end) + fail("Total must be greater than or equal to the range bounary"); + + parse_module_params(argc - 4, argv + 4, false); + + modprobe_collect_simple_options(&modprobe_cmd); + + for (int i = option1_range.start; i <= option1_range.end; i += option1_range.step) { + int j = total - i; + + struct modprobe_param param1, param2; + + param_print_key_value(¶m1, "%s=%d", option1_name, i); + param_print_key_value(¶m2, "%s=%d", option2_name, j); + + modprobe_cmd_add(&modprobe_cmd, param1.value); + modprobe_cmd_add(&modprobe_cmd, param2.value); + + runonce(&modprobe_cmd); + + modprobe_cmd_pop(&modprobe_cmd); + modprobe_cmd_pop(&modprobe_cmd); + + if (i + option1_range.step <= option1_range.end) { + printf("Cooling down (%ds)..\n", cooldown); + if (!dryrun) + sleep(cooldown); + puts(""); + } + } +} + /* ============================= Entry Point ============================== */ int bench_sync_rcu(int argc, const char **argv) @@ -1228,6 +1300,8 @@ int bench_sync_rcu(int argc, const char **argv) cmd = test_once; else if (strcmp(runmode, "range") == 0) cmd = test_range; + else if (strcmp(runmode, "ratio") == 0) + cmd = test_ratio; else usage_with_options(bench_rcu_usage, bench_rcu_options); -- 2.50.1.565.gc32cd1483b-goog

