[v7,27/32] eal/trace: add trace performance test cases

Message ID 20200422190349.3768487-28-jerinj@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: David Marchand
Headers
Series DPDK Trace support |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Jerin Jacob April 22, 2020, 7:03 p.m. UTC
From: Jerin Jacob <jerinj@marvell.com>

This test case shall be used to measure the trace overhead.

Example command to run the performance test case.

echo "trace_perf_autotest" | ./build/app/test/dpdk-test -c 0x3 --trace=.*

Signed-off-by: Jerin Jacob <jerinj@marvell.com>
---
 app/test/Makefile          |   1 +
 app/test/meson.build       |   2 +
 app/test/test_trace_perf.c | 183 +++++++++++++++++++++++++++++++++++++
 3 files changed, 186 insertions(+)
 create mode 100644 app/test/test_trace_perf.c
  

Patch

diff --git a/app/test/Makefile b/app/test/Makefile
index 0b5807d7e..4582eca6c 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -155,6 +155,7 @@  SRCS-y += test_version.c
 SRCS-y += test_func_reentrancy.c
 SRCS-y += test_trace.c
 SRCS-y += test_trace_register.c
+SRCS-y += test_trace_perf.c
 SRCS-y += test_service_cores.c
 
 ifeq ($(CONFIG_RTE_LIBRTE_PMD_RING),y)
diff --git a/app/test/meson.build b/app/test/meson.build
index a0b2c1fa8..a9a8eabcd 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -129,6 +129,7 @@  test_sources = files('commands.c',
 	'test_ticketlock.c',
 	'test_trace.c',
 	'test_trace_register.c',
+	'test_trace_perf.c',
 	'test_version.c',
 	'virtual_pmd.c'
 )
@@ -283,6 +284,7 @@  perf_test_names = [
         'rand_perf_autotest',
         'hash_readwrite_perf_autotest',
         'hash_readwrite_lf_perf_autotest',
+        'trace_perf_autotest',
 ]
 
 driver_test_names = [
diff --git a/app/test/test_trace_perf.c b/app/test/test_trace_perf.c
new file mode 100644
index 000000000..df1c8eb76
--- /dev/null
+++ b/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_malloc.h>
+#include <rte_lcore.h>
+#include <rte_eal_trace.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);