summaryrefslogtreecommitdiffstats
path: root/src/spdk/dpdk/app/test/test_trace_perf.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/spdk/dpdk/app/test/test_trace_perf.c
parentInitial commit. (diff)
downloadceph-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.c183
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);