diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/spdk/dpdk/app/test/test_trace_perf.c | |
parent | Initial commit. (diff) | |
download | ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/spdk/dpdk/app/test/test_trace_perf.c')
-rw-r--r-- | src/spdk/dpdk/app/test/test_trace_perf.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/spdk/dpdk/app/test/test_trace_perf.c b/src/spdk/dpdk/app/test/test_trace_perf.c new file mode 100644 index 000000000..50c7381b7 --- /dev/null +++ b/src/spdk/dpdk/app/test/test_trace_perf.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ + +#include <rte_cycles.h> +#include <rte_debug.h> +#include <rte_eal.h> +#include <rte_eal_trace.h> +#include <rte_malloc.h> +#include <rte_lcore.h> + +#include "test.h" +#include "test_trace.h" + +struct test_data; + +struct lcore_data { + volatile bool done; + volatile bool started; + uint64_t total_cycles; + uint64_t total_calls; +} __rte_cache_aligned; + +struct test_data { + unsigned int nb_workers; + struct lcore_data ldata[]; +} __rte_cache_aligned; + +#define STEP 100 +#define CENT_OPS(OP) do { \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \ +} while (0) + +static void +measure_perf(const char *str, struct test_data *data) +{ + uint64_t hz = rte_get_timer_hz(); + uint64_t total_cycles = 0; + uint64_t total_calls = 0; + double cycles, ns; + unsigned int workers; + + for (workers = 0; workers < data->nb_workers; workers++) { + total_cycles += data->ldata[workers].total_cycles; + total_calls += data->ldata[workers].total_calls; + } + + cycles = total_calls ? (double)total_cycles / (double)total_calls : 0; + cycles /= STEP; + cycles /= 100; /* CENT_OPS */ + + ns = (cycles / (double)hz) * 1E9; + printf("%16s: cycles=%f ns=%f\n", str, cycles, ns); +} + +static void +wait_till_workers_are_ready(struct test_data *data) +{ + unsigned int workers; + + for (workers = 0; workers < data->nb_workers; workers++) + while (!data->ldata[workers].started) + rte_pause(); +} + +static void +signal_workers_to_finish(struct test_data *data) +{ + unsigned int workers; + + for (workers = 0; workers < data->nb_workers; workers++) { + data->ldata[workers].done = 1; + rte_smp_wmb(); + } +} + +#define WORKER_DEFINE(func) \ +static void __rte_noinline \ +__worker_##func(struct lcore_data *ldata) \ +{ \ + uint64_t start; \ + int i; \ + while (!ldata->done) { \ + start = rte_get_timer_cycles(); \ + for (i = 0; i < STEP; i++) \ + CENT_OPS(func); \ + ldata->total_cycles += rte_get_timer_cycles() - start; \ + ldata->total_calls++; \ + } \ +} \ +static int \ +worker_fn_##func(void *arg) \ +{ \ + struct lcore_data *ldata = arg; \ + ldata->started = 1; \ + rte_smp_wmb(); \ + __worker_##func(ldata); \ + return 0; \ +} + + +/* Test to find trace overhead */ +#define GENERIC_VOID rte_eal_trace_generic_void() +#define GENERIC_U64 rte_eal_trace_generic_u64(0x120000) +#define GENERIC_INT rte_eal_trace_generic_int(-34) +#define GENERIC_FLOAT rte_eal_trace_generic_float(3.3f) +#define GENERIC_DOUBLE rte_eal_trace_generic_double(3.66666) +#define GENERIC_STR rte_eal_trace_generic_str("hello world") +#define VOID_FP app_dpdk_test_fp() + +WORKER_DEFINE(GENERIC_VOID) +WORKER_DEFINE(GENERIC_U64) +WORKER_DEFINE(GENERIC_INT) +WORKER_DEFINE(GENERIC_FLOAT) +WORKER_DEFINE(GENERIC_DOUBLE) +WORKER_DEFINE(GENERIC_STR) +WORKER_DEFINE(VOID_FP) + +static void +run_test(const char *str, lcore_function_t f, struct test_data *data, size_t sz) +{ + unsigned int id, worker = 0; + + memset(data, 0, sz); + data->nb_workers = rte_lcore_count() - 1; + RTE_LCORE_FOREACH_SLAVE(id) + rte_eal_remote_launch(f, &data->ldata[worker++], id); + + wait_till_workers_are_ready(data); + rte_delay_ms(100); /* Wait for some time to accumulate the stats */ + measure_perf(str, data); + signal_workers_to_finish(data); + + RTE_LCORE_FOREACH_SLAVE(id) + rte_eal_wait_lcore(id); +} + +static int +test_trace_perf(void) +{ + unsigned int nb_cores, nb_workers; + struct test_data *data; + size_t sz; + + nb_cores = rte_lcore_count(); + nb_workers = nb_cores - 1; + if (nb_cores < 2) { + printf("Need minimum two cores for testing\n"); + return TEST_SKIPPED; + } + + printf("Timer running at %5.2fMHz\n", rte_get_timer_hz()/1E6); + sz = sizeof(struct test_data); + sz += nb_workers * sizeof(struct lcore_data); + + data = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE); + if (data == NULL) { + printf("Failed to allocate memory\n"); + return TEST_FAILED; + } + + run_test("void", worker_fn_GENERIC_VOID, data, sz); + run_test("u64", worker_fn_GENERIC_U64, data, sz); + run_test("int", worker_fn_GENERIC_INT, data, sz); + run_test("float", worker_fn_GENERIC_FLOAT, data, sz); + run_test("double", worker_fn_GENERIC_DOUBLE, data, sz); + run_test("string", worker_fn_GENERIC_STR, data, sz); + run_test("void_fp", worker_fn_VOID_FP, data, sz); + + rte_free(data); + return TEST_SUCCESS; +} + +REGISTER_TEST_COMMAND(trace_perf_autotest, test_trace_perf); |