brintos

brintos / linux-shallow public Read only

0
0
Text · 6.0 KiB · e2ff8ea Raw
259 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */3 4#include <sys/types.h>5#include <sys/socket.h>6#include <pthread.h>7#include <argp.h>8 9#include "bench.h"10#include "bench_local_storage_create.skel.h"11 12struct thread {13	int *fds;14	pthread_t *pthds;15	int *pthd_results;16};17 18static struct bench_local_storage_create *skel;19static struct thread *threads;20static long create_owner_errs;21static int storage_type = BPF_MAP_TYPE_SK_STORAGE;22static int batch_sz = 32;23 24enum {25	ARG_BATCH_SZ = 9000,26	ARG_STORAGE_TYPE = 9001,27};28 29static const struct argp_option opts[] = {30	{ "batch-size", ARG_BATCH_SZ, "BATCH_SIZE", 0,31	  "The number of storage creations in each batch" },32	{ "storage-type", ARG_STORAGE_TYPE, "STORAGE_TYPE", 0,33	  "The type of local storage to test (socket or task)" },34	{},35};36 37static error_t parse_arg(int key, char *arg, struct argp_state *state)38{39	int ret;40 41	switch (key) {42	case ARG_BATCH_SZ:43		ret = atoi(arg);44		if (ret < 1) {45			fprintf(stderr, "invalid batch-size\n");46			argp_usage(state);47		}48		batch_sz = ret;49		break;50	case ARG_STORAGE_TYPE:51		if (!strcmp(arg, "task")) {52			storage_type = BPF_MAP_TYPE_TASK_STORAGE;53		} else if (!strcmp(arg, "socket")) {54			storage_type = BPF_MAP_TYPE_SK_STORAGE;55		} else {56			fprintf(stderr, "invalid storage-type (socket or task)\n");57			argp_usage(state);58		}59		break;60	default:61		return ARGP_ERR_UNKNOWN;62	}63 64	return 0;65}66 67const struct argp bench_local_storage_create_argp = {68	.options = opts,69	.parser = parse_arg,70};71 72static void validate(void)73{74	if (env.consumer_cnt != 0) {75		fprintf(stderr,76			"local-storage-create benchmark does not need consumer\n");77		exit(1);78	}79}80 81static void setup(void)82{83	int i;84 85	skel = bench_local_storage_create__open_and_load();86	if (!skel) {87		fprintf(stderr, "error loading skel\n");88		exit(1);89	}90 91	skel->bss->bench_pid = getpid();92	if (storage_type == BPF_MAP_TYPE_SK_STORAGE) {93		if (!bpf_program__attach(skel->progs.socket_post_create)) {94			fprintf(stderr, "Error attaching bpf program\n");95			exit(1);96		}97	} else {98		if (!bpf_program__attach(skel->progs.sched_process_fork)) {99			fprintf(stderr, "Error attaching bpf program\n");100			exit(1);101		}102	}103 104	if (!bpf_program__attach(skel->progs.kmalloc)) {105		fprintf(stderr, "Error attaching bpf program\n");106		exit(1);107	}108 109	threads = calloc(env.producer_cnt, sizeof(*threads));110 111	if (!threads) {112		fprintf(stderr, "cannot alloc thread_res\n");113		exit(1);114	}115 116	for (i = 0; i < env.producer_cnt; i++) {117		struct thread *t = &threads[i];118 119		if (storage_type == BPF_MAP_TYPE_SK_STORAGE) {120			t->fds = malloc(batch_sz * sizeof(*t->fds));121			if (!t->fds) {122				fprintf(stderr, "cannot alloc t->fds\n");123				exit(1);124			}125		} else {126			t->pthds = malloc(batch_sz * sizeof(*t->pthds));127			if (!t->pthds) {128				fprintf(stderr, "cannot alloc t->pthds\n");129				exit(1);130			}131			t->pthd_results = malloc(batch_sz * sizeof(*t->pthd_results));132			if (!t->pthd_results) {133				fprintf(stderr, "cannot alloc t->pthd_results\n");134				exit(1);135			}136		}137	}138}139 140static void measure(struct bench_res *res)141{142	res->hits = atomic_swap(&skel->bss->create_cnts, 0);143	res->drops = atomic_swap(&skel->bss->kmalloc_cnts, 0);144}145 146static void *sk_producer(void *input)147{148	struct thread *t = &threads[(long)(input)];149	int *fds = t->fds;150	int i;151 152	while (true) {153		for (i = 0; i < batch_sz; i++) {154			fds[i] = socket(AF_INET6, SOCK_DGRAM, 0);155			if (fds[i] == -1)156				atomic_inc(&create_owner_errs);157		}158 159		for (i = 0; i < batch_sz; i++) {160			if (fds[i] != -1)161				close(fds[i]);162		}163	}164 165	return NULL;166}167 168static void *thread_func(void *arg)169{170	return NULL;171}172 173static void *task_producer(void *input)174{175	struct thread *t = &threads[(long)(input)];176	pthread_t *pthds = t->pthds;177	int *pthd_results = t->pthd_results;178	int i;179 180	while (true) {181		for (i = 0; i < batch_sz; i++) {182			pthd_results[i] = pthread_create(&pthds[i], NULL, thread_func, NULL);183			if (pthd_results[i])184				atomic_inc(&create_owner_errs);185		}186 187		for (i = 0; i < batch_sz; i++) {188			if (!pthd_results[i])189				pthread_join(pthds[i], NULL);190		}191	}192 193	return NULL;194}195 196static void *producer(void *input)197{198	if (storage_type == BPF_MAP_TYPE_SK_STORAGE)199		return sk_producer(input);200	else201		return task_producer(input);202}203 204static void report_progress(int iter, struct bench_res *res, long delta_ns)205{206	double creates_per_sec, kmallocs_per_create;207 208	creates_per_sec = res->hits / 1000.0 / (delta_ns / 1000000000.0);209	kmallocs_per_create = (double)res->drops / res->hits;210 211	printf("Iter %3d (%7.3lfus): ",212	       iter, (delta_ns - 1000000000) / 1000.0);213	printf("creates %8.3lfk/s (%7.3lfk/prod), ",214	       creates_per_sec, creates_per_sec / env.producer_cnt);215	printf("%3.2lf kmallocs/create\n", kmallocs_per_create);216}217 218static void report_final(struct bench_res res[], int res_cnt)219{220	double creates_mean = 0.0, creates_stddev = 0.0;221	long total_creates = 0, total_kmallocs = 0;222	int i;223 224	for (i = 0; i < res_cnt; i++) {225		creates_mean += res[i].hits / 1000.0 / (0.0 + res_cnt);226		total_creates += res[i].hits;227		total_kmallocs += res[i].drops;228	}229 230	if (res_cnt > 1)  {231		for (i = 0; i < res_cnt; i++)232			creates_stddev += (creates_mean - res[i].hits / 1000.0) *233				       (creates_mean - res[i].hits / 1000.0) /234				       (res_cnt - 1.0);235		creates_stddev = sqrt(creates_stddev);236	}237	printf("Summary: creates %8.3lf \u00B1 %5.3lfk/s (%7.3lfk/prod), ",238	       creates_mean, creates_stddev, creates_mean / env.producer_cnt);239	printf("%4.2lf kmallocs/create\n", (double)total_kmallocs / total_creates);240	if (create_owner_errs || skel->bss->create_errs)241		printf("%s() errors %ld create_errs %ld\n",242		       storage_type == BPF_MAP_TYPE_SK_STORAGE ?243		       "socket" : "pthread_create",244		       create_owner_errs,245		       skel->bss->create_errs);246}247 248/* Benchmark performance of creating bpf local storage  */249const struct bench bench_local_storage_create = {250	.name = "local-storage-create",251	.argp = &bench_local_storage_create_argp,252	.validate = validate,253	.setup = setup,254	.producer_thread = producer,255	.measure = measure,256	.report_progress = report_progress,257	.report_final = report_final,258};259