Commit 22ff7aea authored by Anton Protopopov's avatar Anton Protopopov Committed by Andrii Nakryiko

selftest/bpf/benchs: Enhance argp parsing

To parse command line the bench utility uses the argp_parse() function. This
function takes as an argument a parent 'struct argp' structure which defines
common command line options and an array of children 'struct argp' structures
which defines additional command line options for particular benchmarks. This
implementation doesn't allow benchmarks to share option names, e.g., if two
benchmarks want to use, say, the --option option, then only one of them will
succeed (the first one encountered in the array).  This will be convenient if
same option names could be used in different benchmarks (with the same
semantics, e.g., --nr_loops=N).

Fix this by calling the argp_parse() function twice. The first call is the same
as it was before, with all children argps, and helps to find the benchmark name
and to print a combined help message if anything is wrong.  Given the name, we
can call the argp_parse the second time, but now the children array points only
to a correct benchmark thus always calling the correct parsers. (If there's no
a specific list of arguments, then only one call to argp_parse will be done.)
Signed-off-by: default avatarAnton Protopopov <aspsk@isovalent.com>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20230213091519.1202813-4-aspsk@isovalent.com
parent 2f1c5963
...@@ -287,10 +287,11 @@ static const struct argp_child bench_parsers[] = { ...@@ -287,10 +287,11 @@ static const struct argp_child bench_parsers[] = {
{}, {},
}; };
/* Make pos_args global, so that we can run argp_parse twice, if necessary */
static int pos_args;
static error_t parse_arg(int key, char *arg, struct argp_state *state) static error_t parse_arg(int key, char *arg, struct argp_state *state)
{ {
static int pos_args;
switch (key) { switch (key) {
case 'v': case 'v':
env.verbose = true; env.verbose = true;
...@@ -359,7 +360,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) ...@@ -359,7 +360,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
return 0; return 0;
} }
static void parse_cmdline_args(int argc, char **argv) static void parse_cmdline_args_init(int argc, char **argv)
{ {
static const struct argp argp = { static const struct argp argp = {
.options = opts, .options = opts,
...@@ -369,9 +370,25 @@ static void parse_cmdline_args(int argc, char **argv) ...@@ -369,9 +370,25 @@ static void parse_cmdline_args(int argc, char **argv)
}; };
if (argp_parse(&argp, argc, argv, 0, NULL, NULL)) if (argp_parse(&argp, argc, argv, 0, NULL, NULL))
exit(1); exit(1);
if (!env.list && !env.bench_name) { }
argp_help(&argp, stderr, ARGP_HELP_DOC, "bench");
exit(1); static void parse_cmdline_args_final(int argc, char **argv)
{
struct argp_child bench_parsers[2] = {};
const struct argp argp = {
.options = opts,
.parser = parse_arg,
.doc = argp_program_doc,
.children = bench_parsers,
};
/* Parse arguments the second time with the correct set of parsers */
if (bench->argp) {
bench_parsers[0].argp = bench->argp;
bench_parsers[0].header = bench->name;
pos_args = 0;
if (argp_parse(&argp, argc, argv, 0, NULL, NULL))
exit(1);
} }
} }
...@@ -531,15 +548,14 @@ static const struct bench *benchs[] = { ...@@ -531,15 +548,14 @@ static const struct bench *benchs[] = {
&bench_local_storage_tasks_trace, &bench_local_storage_tasks_trace,
}; };
static void setup_benchmark() static void find_benchmark(void)
{ {
int i, err; int i;
if (!env.bench_name) { if (!env.bench_name) {
fprintf(stderr, "benchmark name is not specified\n"); fprintf(stderr, "benchmark name is not specified\n");
exit(1); exit(1);
} }
for (i = 0; i < ARRAY_SIZE(benchs); i++) { for (i = 0; i < ARRAY_SIZE(benchs); i++) {
if (strcmp(benchs[i]->name, env.bench_name) == 0) { if (strcmp(benchs[i]->name, env.bench_name) == 0) {
bench = benchs[i]; bench = benchs[i];
...@@ -550,6 +566,11 @@ static void setup_benchmark() ...@@ -550,6 +566,11 @@ static void setup_benchmark()
fprintf(stderr, "benchmark '%s' not found\n", env.bench_name); fprintf(stderr, "benchmark '%s' not found\n", env.bench_name);
exit(1); exit(1);
} }
}
static void setup_benchmark(void)
{
int i, err;
printf("Setting up benchmark '%s'...\n", bench->name); printf("Setting up benchmark '%s'...\n", bench->name);
...@@ -621,7 +642,7 @@ static void collect_measurements(long delta_ns) { ...@@ -621,7 +642,7 @@ static void collect_measurements(long delta_ns) {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
parse_cmdline_args(argc, argv); parse_cmdline_args_init(argc, argv);
if (env.list) { if (env.list) {
int i; int i;
...@@ -633,6 +654,9 @@ int main(int argc, char **argv) ...@@ -633,6 +654,9 @@ int main(int argc, char **argv)
return 0; return 0;
} }
find_benchmark();
parse_cmdline_args_final(argc, argv);
setup_benchmark(); setup_benchmark();
setup_timer(); setup_timer();
......
...@@ -47,6 +47,7 @@ struct bench_res { ...@@ -47,6 +47,7 @@ struct bench_res {
struct bench { struct bench {
const char *name; const char *name;
const struct argp *argp;
void (*validate)(void); void (*validate)(void);
void (*setup)(void); void (*setup)(void);
void *(*producer_thread)(void *ctx); void *(*producer_thread)(void *ctx);
......
...@@ -428,6 +428,7 @@ static void *consumer(void *input) ...@@ -428,6 +428,7 @@ static void *consumer(void *input)
const struct bench bench_bloom_lookup = { const struct bench bench_bloom_lookup = {
.name = "bloom-lookup", .name = "bloom-lookup",
.argp = &bench_bloom_map_argp,
.validate = validate, .validate = validate,
.setup = bloom_lookup_setup, .setup = bloom_lookup_setup,
.producer_thread = producer, .producer_thread = producer,
...@@ -439,6 +440,7 @@ const struct bench bench_bloom_lookup = { ...@@ -439,6 +440,7 @@ const struct bench bench_bloom_lookup = {
const struct bench bench_bloom_update = { const struct bench bench_bloom_update = {
.name = "bloom-update", .name = "bloom-update",
.argp = &bench_bloom_map_argp,
.validate = validate, .validate = validate,
.setup = bloom_update_setup, .setup = bloom_update_setup,
.producer_thread = producer, .producer_thread = producer,
...@@ -450,6 +452,7 @@ const struct bench bench_bloom_update = { ...@@ -450,6 +452,7 @@ const struct bench bench_bloom_update = {
const struct bench bench_bloom_false_positive = { const struct bench bench_bloom_false_positive = {
.name = "bloom-false-positive", .name = "bloom-false-positive",
.argp = &bench_bloom_map_argp,
.validate = validate, .validate = validate,
.setup = false_positive_setup, .setup = false_positive_setup,
.producer_thread = producer, .producer_thread = producer,
...@@ -461,6 +464,7 @@ const struct bench bench_bloom_false_positive = { ...@@ -461,6 +464,7 @@ const struct bench bench_bloom_false_positive = {
const struct bench bench_hashmap_without_bloom = { const struct bench bench_hashmap_without_bloom = {
.name = "hashmap-without-bloom", .name = "hashmap-without-bloom",
.argp = &bench_bloom_map_argp,
.validate = validate, .validate = validate,
.setup = hashmap_no_bloom_setup, .setup = hashmap_no_bloom_setup,
.producer_thread = producer, .producer_thread = producer,
...@@ -472,6 +476,7 @@ const struct bench bench_hashmap_without_bloom = { ...@@ -472,6 +476,7 @@ const struct bench bench_hashmap_without_bloom = {
const struct bench bench_hashmap_with_bloom = { const struct bench bench_hashmap_with_bloom = {
.name = "hashmap-with-bloom", .name = "hashmap-with-bloom",
.argp = &bench_bloom_map_argp,
.validate = validate, .validate = validate,
.setup = hashmap_with_bloom_setup, .setup = hashmap_with_bloom_setup,
.producer_thread = producer, .producer_thread = producer,
......
...@@ -95,6 +95,7 @@ static void setup(void) ...@@ -95,6 +95,7 @@ static void setup(void)
const struct bench bench_bpf_loop = { const struct bench bench_bpf_loop = {
.name = "bpf-loop", .name = "bpf-loop",
.argp = &bench_bpf_loop_argp,
.validate = validate, .validate = validate,
.setup = setup, .setup = setup,
.producer_thread = producer, .producer_thread = producer,
......
...@@ -255,6 +255,7 @@ static void *producer(void *input) ...@@ -255,6 +255,7 @@ static void *producer(void *input)
*/ */
const struct bench bench_local_storage_cache_seq_get = { const struct bench bench_local_storage_cache_seq_get = {
.name = "local-storage-cache-seq-get", .name = "local-storage-cache-seq-get",
.argp = &bench_local_storage_argp,
.validate = validate, .validate = validate,
.setup = local_storage_cache_get_setup, .setup = local_storage_cache_get_setup,
.producer_thread = producer, .producer_thread = producer,
...@@ -266,6 +267,7 @@ const struct bench bench_local_storage_cache_seq_get = { ...@@ -266,6 +267,7 @@ const struct bench bench_local_storage_cache_seq_get = {
const struct bench bench_local_storage_cache_interleaved_get = { const struct bench bench_local_storage_cache_interleaved_get = {
.name = "local-storage-cache-int-get", .name = "local-storage-cache-int-get",
.argp = &bench_local_storage_argp,
.validate = validate, .validate = validate,
.setup = local_storage_cache_get_interleaved_setup, .setup = local_storage_cache_get_interleaved_setup,
.producer_thread = producer, .producer_thread = producer,
...@@ -277,6 +279,7 @@ const struct bench bench_local_storage_cache_interleaved_get = { ...@@ -277,6 +279,7 @@ const struct bench bench_local_storage_cache_interleaved_get = {
const struct bench bench_local_storage_cache_hashmap_control = { const struct bench bench_local_storage_cache_hashmap_control = {
.name = "local-storage-cache-hashmap-control", .name = "local-storage-cache-hashmap-control",
.argp = &bench_local_storage_argp,
.validate = validate, .validate = validate,
.setup = hashmap_setup, .setup = hashmap_setup,
.producer_thread = producer, .producer_thread = producer,
......
...@@ -271,6 +271,7 @@ static void report_final(struct bench_res res[], int res_cnt) ...@@ -271,6 +271,7 @@ static void report_final(struct bench_res res[], int res_cnt)
*/ */
const struct bench bench_local_storage_tasks_trace = { const struct bench bench_local_storage_tasks_trace = {
.name = "local-storage-tasks-trace", .name = "local-storage-tasks-trace",
.argp = &bench_local_storage_rcu_tasks_trace_argp,
.validate = validate, .validate = validate,
.setup = local_storage_tasks_trace_setup, .setup = local_storage_tasks_trace_setup,
.producer_thread = producer, .producer_thread = producer,
......
...@@ -518,6 +518,7 @@ static void *perfbuf_custom_consumer(void *input) ...@@ -518,6 +518,7 @@ static void *perfbuf_custom_consumer(void *input)
const struct bench bench_rb_libbpf = { const struct bench bench_rb_libbpf = {
.name = "rb-libbpf", .name = "rb-libbpf",
.argp = &bench_ringbufs_argp,
.validate = bufs_validate, .validate = bufs_validate,
.setup = ringbuf_libbpf_setup, .setup = ringbuf_libbpf_setup,
.producer_thread = bufs_sample_producer, .producer_thread = bufs_sample_producer,
...@@ -529,6 +530,7 @@ const struct bench bench_rb_libbpf = { ...@@ -529,6 +530,7 @@ const struct bench bench_rb_libbpf = {
const struct bench bench_rb_custom = { const struct bench bench_rb_custom = {
.name = "rb-custom", .name = "rb-custom",
.argp = &bench_ringbufs_argp,
.validate = bufs_validate, .validate = bufs_validate,
.setup = ringbuf_custom_setup, .setup = ringbuf_custom_setup,
.producer_thread = bufs_sample_producer, .producer_thread = bufs_sample_producer,
...@@ -540,6 +542,7 @@ const struct bench bench_rb_custom = { ...@@ -540,6 +542,7 @@ const struct bench bench_rb_custom = {
const struct bench bench_pb_libbpf = { const struct bench bench_pb_libbpf = {
.name = "pb-libbpf", .name = "pb-libbpf",
.argp = &bench_ringbufs_argp,
.validate = bufs_validate, .validate = bufs_validate,
.setup = perfbuf_libbpf_setup, .setup = perfbuf_libbpf_setup,
.producer_thread = bufs_sample_producer, .producer_thread = bufs_sample_producer,
...@@ -551,6 +554,7 @@ const struct bench bench_pb_libbpf = { ...@@ -551,6 +554,7 @@ const struct bench bench_pb_libbpf = {
const struct bench bench_pb_custom = { const struct bench bench_pb_custom = {
.name = "pb-custom", .name = "pb-custom",
.argp = &bench_ringbufs_argp,
.validate = bufs_validate, .validate = bufs_validate,
.setup = perfbuf_libbpf_setup, .setup = perfbuf_libbpf_setup,
.producer_thread = bufs_sample_producer, .producer_thread = bufs_sample_producer,
......
...@@ -140,6 +140,7 @@ static void strncmp_measure(struct bench_res *res) ...@@ -140,6 +140,7 @@ static void strncmp_measure(struct bench_res *res)
const struct bench bench_strncmp_no_helper = { const struct bench bench_strncmp_no_helper = {
.name = "strncmp-no-helper", .name = "strncmp-no-helper",
.argp = &bench_strncmp_argp,
.validate = strncmp_validate, .validate = strncmp_validate,
.setup = strncmp_no_helper_setup, .setup = strncmp_no_helper_setup,
.producer_thread = strncmp_producer, .producer_thread = strncmp_producer,
...@@ -151,6 +152,7 @@ const struct bench bench_strncmp_no_helper = { ...@@ -151,6 +152,7 @@ const struct bench bench_strncmp_no_helper = {
const struct bench bench_strncmp_helper = { const struct bench bench_strncmp_helper = {
.name = "strncmp-helper", .name = "strncmp-helper",
.argp = &bench_strncmp_argp,
.validate = strncmp_validate, .validate = strncmp_validate,
.setup = strncmp_helper_setup, .setup = strncmp_helper_setup,
.producer_thread = strncmp_producer, .producer_thread = strncmp_producer,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment