0001
0002
0003 #include <argp.h>
0004 #include "bench.h"
0005 #include "strncmp_bench.skel.h"
0006
0007 static struct strncmp_ctx {
0008 struct strncmp_bench *skel;
0009 } ctx;
0010
0011 static struct strncmp_args {
0012 u32 cmp_str_len;
0013 } args = {
0014 .cmp_str_len = 32,
0015 };
0016
0017 enum {
0018 ARG_CMP_STR_LEN = 5000,
0019 };
0020
0021 static const struct argp_option opts[] = {
0022 { "cmp-str-len", ARG_CMP_STR_LEN, "CMP_STR_LEN", 0,
0023 "Set the length of compared string" },
0024 {},
0025 };
0026
0027 static error_t strncmp_parse_arg(int key, char *arg, struct argp_state *state)
0028 {
0029 switch (key) {
0030 case ARG_CMP_STR_LEN:
0031 args.cmp_str_len = strtoul(arg, NULL, 10);
0032 if (!args.cmp_str_len ||
0033 args.cmp_str_len >= sizeof(ctx.skel->bss->str)) {
0034 fprintf(stderr, "Invalid cmp str len (limit %zu)\n",
0035 sizeof(ctx.skel->bss->str));
0036 argp_usage(state);
0037 }
0038 break;
0039 default:
0040 return ARGP_ERR_UNKNOWN;
0041 }
0042
0043 return 0;
0044 }
0045
0046 const struct argp bench_strncmp_argp = {
0047 .options = opts,
0048 .parser = strncmp_parse_arg,
0049 };
0050
0051 static void strncmp_validate(void)
0052 {
0053 if (env.consumer_cnt != 1) {
0054 fprintf(stderr, "strncmp benchmark doesn't support multi-consumer!\n");
0055 exit(1);
0056 }
0057 }
0058
0059 static void strncmp_setup(void)
0060 {
0061 int err;
0062 char *target;
0063 size_t i, sz;
0064
0065 sz = sizeof(ctx.skel->rodata->target);
0066 if (!sz || sz < sizeof(ctx.skel->bss->str)) {
0067 fprintf(stderr, "invalid string size (target %zu, src %zu)\n",
0068 sz, sizeof(ctx.skel->bss->str));
0069 exit(1);
0070 }
0071
0072 setup_libbpf();
0073
0074 ctx.skel = strncmp_bench__open();
0075 if (!ctx.skel) {
0076 fprintf(stderr, "failed to open skeleton\n");
0077 exit(1);
0078 }
0079
0080 srandom(time(NULL));
0081 target = ctx.skel->rodata->target;
0082 for (i = 0; i < sz - 1; i++)
0083 target[i] = '1' + random() % 9;
0084 target[sz - 1] = '\0';
0085
0086 ctx.skel->rodata->cmp_str_len = args.cmp_str_len;
0087
0088 memcpy(ctx.skel->bss->str, target, args.cmp_str_len);
0089 ctx.skel->bss->str[args.cmp_str_len] = '\0';
0090
0091 ctx.skel->bss->str[args.cmp_str_len - 1] -= 1;
0092
0093 err = strncmp_bench__load(ctx.skel);
0094 if (err) {
0095 fprintf(stderr, "failed to load skeleton\n");
0096 strncmp_bench__destroy(ctx.skel);
0097 exit(1);
0098 }
0099 }
0100
0101 static void strncmp_attach_prog(struct bpf_program *prog)
0102 {
0103 struct bpf_link *link;
0104
0105 link = bpf_program__attach(prog);
0106 if (!link) {
0107 fprintf(stderr, "failed to attach program!\n");
0108 exit(1);
0109 }
0110 }
0111
0112 static void strncmp_no_helper_setup(void)
0113 {
0114 strncmp_setup();
0115 strncmp_attach_prog(ctx.skel->progs.strncmp_no_helper);
0116 }
0117
0118 static void strncmp_helper_setup(void)
0119 {
0120 strncmp_setup();
0121 strncmp_attach_prog(ctx.skel->progs.strncmp_helper);
0122 }
0123
0124 static void *strncmp_producer(void *ctx)
0125 {
0126 while (true)
0127 (void)syscall(__NR_getpgid);
0128 return NULL;
0129 }
0130
0131 static void *strncmp_consumer(void *ctx)
0132 {
0133 return NULL;
0134 }
0135
0136 static void strncmp_measure(struct bench_res *res)
0137 {
0138 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
0139 }
0140
0141 const struct bench bench_strncmp_no_helper = {
0142 .name = "strncmp-no-helper",
0143 .validate = strncmp_validate,
0144 .setup = strncmp_no_helper_setup,
0145 .producer_thread = strncmp_producer,
0146 .consumer_thread = strncmp_consumer,
0147 .measure = strncmp_measure,
0148 .report_progress = hits_drops_report_progress,
0149 .report_final = hits_drops_report_final,
0150 };
0151
0152 const struct bench bench_strncmp_helper = {
0153 .name = "strncmp-helper",
0154 .validate = strncmp_validate,
0155 .setup = strncmp_helper_setup,
0156 .producer_thread = strncmp_producer,
0157 .consumer_thread = strncmp_consumer,
0158 .measure = strncmp_measure,
0159 .report_progress = hits_drops_report_progress,
0160 .report_final = hits_drops_report_final,
0161 };