All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Morten Brørup" <mb@smartsharesystems.com>
To: dev@dpdk.org, Jerin Jacob <jerinj@marvell.com>,
	Kiran Kumar K <kirankumark@marvell.com>,
	Nithin Dabilpuram <ndabilpuram@marvell.com>,
	Zhirun Yan <yanzhirun_163@163.com>,
	Saeed Bishara <saeed.bishara.os@gmail.com>
Cc: "Morten Brørup" <mb@smartsharesystems.com>
Subject: [PATCH v7] graph: add optional profiling stats
Date: Fri,  3 Jul 2026 13:53:01 +0000	[thread overview]
Message-ID: <20260703135301.3040663-1-mb@smartsharesystems.com> (raw)
In-Reply-To: <20260619202047.2809165-1-mb@smartsharesystems.com>

graph: add optional profiling stats

Added graph node profiling stats, build time configurable by enabling
RTE_GRAPH_PROFILE in rte_config.h.

Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
---
v7:
* Use RTE_DIM() in histogram for loop.
* Added static_assert for histogram index values.
* Minor details to please checkpatch.
  Although I disagree with requiring a space when indexing into
  a constant array "(const type []){values} [idx];",
  I have changed the code to comply.
v6:
* Consolidate the four histogram entries into one array. (Saeed Bishara)
* Sample at 32 objs instead of a half burst. (Saeed Bishara)
* Moved stats to different location in rte_node structure. (Jerin)
* Minor details to please checkpatch.
v5:
* Added stats for a half burst and a full burst.
v4:
* Added documentation. (AI)
* Added more comments. (AI)
* Improved dump. (AI)
* Debug shows both cycles/call and cycles/obj.
v3:
* Debug shows cycles/obj instead of cycles/call.
* Fixed missing --in-reply-to.
v2:
* Fixed indentation.
---
 config/rte_config.h                 |  1 +
 doc/guides/prog_guide/graph_lib.rst |  1 +
 lib/graph/graph_debug.c             | 48 +++++++++++++++++++++++++++++
 lib/graph/node.c                    |  2 ++
 lib/graph/rte_graph_worker_common.h | 29 +++++++++++++++--
 5 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/config/rte_config.h b/config/rte_config.h
index 0447cdf2ad..1942c1b1ec 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -106,6 +106,7 @@
 /* rte_graph defines */
 #define RTE_GRAPH_BURST_SIZE 256
 #define RTE_LIBRTE_GRAPH_STATS 1
+/* RTE_GRAPH_PROFILE is not set */
 
 /****** driver defines ********/
 
diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst
index 8dd49c19d2..bc36042296 100644
--- a/doc/guides/prog_guide/graph_lib.rst
+++ b/doc/guides/prog_guide/graph_lib.rst
@@ -49,6 +49,7 @@ Performance tuning parameters
   RTE_GRAPH_BURST_SIZE config option.
   The testing shows, on x86 and arm64 servers, The sweet spot is 256 burst
   size. While on arm64 embedded SoCs, it is either 64 or 128.
+- Enable the ``RTE_GRAPH_PROFILE`` config option for more profiling details.
 - Disable node statistics (using ``RTE_LIBRTE_GRAPH_STATS`` config option)
   if not needed.
 
diff --git a/lib/graph/graph_debug.c b/lib/graph/graph_debug.c
index e3b8cccdc1..427c6a6e77 100644
--- a/lib/graph/graph_debug.c
+++ b/lib/graph/graph_debug.c
@@ -93,6 +93,54 @@ rte_graph_obj_dump(FILE *f, struct rte_graph *g, bool all)
 				n->dispatch.total_sched_fail);
 		}
 		fprintf(f, "       total_calls=%" PRId64 "\n", n->total_calls);
+		if (rte_graph_has_stats_feature())
+			fprintf(f, "       total_cycles=%" PRIu64 ", avg cycles/call=%.1f\n",
+					n->total_cycles,
+					n->total_calls == 0 ? 0.0 :
+					(double)n->total_cycles / (double)n->total_calls);
+#ifdef RTE_GRAPH_PROFILE
+		int64_t calls_other = n->total_calls;
+		int64_t cycles_other = n->total_cycles;
+		int64_t objs_other = n->total_objs;
+		for (int idx = 0; idx < RTE_DIM(n->usage_stats) + 1; idx++) {
+			uint64_t calls;
+			uint64_t cycles;
+			double objs_per_call;
+			if (idx < RTE_DIM(n->usage_stats)) {
+				static_assert(RTE_DIM(n->usage_stats) == 4);
+				uint16_t idx_objs = (const uint16_t []){0, 1, 32,
+						RTE_GRAPH_BURST_SIZE} [idx];
+				fprintf(f, "       objs[%u]\n", idx_objs);
+				calls = n->usage_stats[idx].calls;
+				cycles = n->usage_stats[idx].cycles;
+				objs_per_call = (double)idx_objs;
+				calls_other -= calls;
+				cycles_other -= cycles;
+				objs_other -= idx_objs * calls;
+			} else {
+				fprintf(f, "       objs[other]\n");
+				if (calls_other > 0 && cycles_other > 0 && objs_other > 0) {
+					calls = calls_other;
+					cycles = cycles_other;
+					objs_per_call = (double)objs_other / (double)calls_other;
+					fprintf(f, "         avg objs/call=%.1f\n", objs_per_call);
+				} else {
+					calls = 0;
+					cycles = 0;
+					objs_per_call = 0.0;
+				}
+			}
+			fprintf(f, "         calls=%" PRIu64, calls);
+			if (calls != 0)
+				fprintf(f, ", cycles=%" PRIu64 ", avg cycles/call=%.1f",
+						cycles,
+						(double)cycles / (double)calls);
+			if (calls != 0 && objs_per_call != 0.0)
+				fprintf(f, ", avg cycles/obj=%.1f",
+						(double)cycles / (double)calls / objs_per_call);
+			fprintf(f, "\n");
+		}
+#endif
 		for (i = 0; i < n->nb_edges; i++)
 			fprintf(f, "          edge[%d] <%s>\n", i,
 				n->nodes[i]->name);
diff --git a/lib/graph/node.c b/lib/graph/node.c
index 1fce3e6632..19b38881ae 100644
--- a/lib/graph/node.c
+++ b/lib/graph/node.c
@@ -110,10 +110,12 @@ __rte_node_register(const struct rte_node_register *reg)
 	rte_edge_t i;
 	size_t sz;
 
+#ifndef RTE_GRAPH_PROFILE
 	/* Limit Node specific metadata to one cacheline on 64B CL machine */
 	RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
 			  offsetof(struct rte_node, ctx)) !=
 			 RTE_CACHE_LINE_MIN_SIZE);
+#endif
 
 	graph_spinlock_lock();
 
diff --git a/lib/graph/rte_graph_worker_common.h b/lib/graph/rte_graph_worker_common.h
index 4ab53a533e..bac0fc534e 100644
--- a/lib/graph/rte_graph_worker_common.h
+++ b/lib/graph/rte_graph_worker_common.h
@@ -121,6 +121,14 @@ struct __rte_cache_aligned rte_node {
 	rte_graph_off_t xstat_off; /**< Offset to xstat counters. */
 
 	/** Fast path area cache line 2. */
+#ifdef RTE_GRAPH_PROFILE
+	/** Usage when this node processed 0, 1, 32 or a full burst of objects. */
+	struct __rte_cache_aligned {
+		uint64_t calls;     /**< Calls done. */
+		uint64_t cycles;    /**< Cycles spent. */
+	} usage_stats[4];
+	/** Fast path area cache line 3. */
+#endif
 	__extension__ struct __rte_cache_aligned {
 #define RTE_NODE_CTX_SZ 16
 		union {
@@ -148,8 +156,10 @@ struct __rte_cache_aligned rte_node {
 	};
 };
 
+#ifndef RTE_GRAPH_PROFILE
 static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
 	== RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
+#endif
 
 /**
  * @internal
@@ -197,7 +207,7 @@ void __rte_node_stream_alloc_size(struct rte_graph *graph,
 static __rte_always_inline void
 __rte_node_process(struct rte_graph *graph, struct rte_node *node)
 {
-	uint64_t start;
+	uint64_t cycles;
 	uint16_t rc;
 	void **objs;
 
@@ -206,11 +216,24 @@ __rte_node_process(struct rte_graph *graph, struct rte_node *node)
 	rte_prefetch0(objs);
 
 	if (rte_graph_has_stats_feature()) {
-		start = rte_rdtsc();
+		cycles = -rte_rdtsc();
 		rc = node->process(graph, node, objs, node->idx);
-		node->total_cycles += rte_rdtsc() - start;
+		cycles += rte_rdtsc();
+		node->total_cycles += cycles;
 		node->total_calls++;
 		node->total_objs += rc;
+#ifdef RTE_GRAPH_PROFILE
+		if (rc <= 1) {
+			node->usage_stats[rc].calls++;
+			node->usage_stats[rc].cycles += cycles;
+		} else if (rc == 32) {
+			node->usage_stats[2].calls++;
+			node->usage_stats[2].cycles += cycles;
+		} else if (rc == RTE_GRAPH_BURST_SIZE) {
+			node->usage_stats[3].calls++;
+			node->usage_stats[3].cycles += cycles;
+		}
+#endif
 	} else {
 		node->process(graph, node, objs, node->idx);
 	}
-- 
2.43.0


  parent reply	other threads:[~2026-07-03 13:53 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-19 20:20 [PATCH] graph: add optional profiling stats Morten Brørup
2026-06-19 20:56 ` [PATCH v3] " Morten Brørup
2026-06-21 17:55 ` [PATCH v4] " Morten Brørup
2026-06-21 18:41 ` [PATCH v5] " Morten Brørup
2026-06-23  5:13   ` Jerin Jacob
2026-06-23  6:45     ` Morten Brørup
2026-06-23  6:56       ` Jerin Jacob
2026-06-23  7:10         ` Morten Brørup
2026-06-23  9:08           ` Jerin Jacob
2026-08-10  6:28             ` Morten Brørup
2026-06-23  8:33         ` saeed bishara
2026-06-23 12:04           ` Morten Brørup
2026-06-23 14:10             ` saeed bishara
2026-06-24  7:59               ` Morten Brørup
2026-06-24 13:09                 ` saeed bishara
2026-07-03 13:18 ` [PATCH v6] " Morten Brørup
2026-07-03 13:53 ` Morten Brørup [this message]
2026-07-03 14:22 ` [PATCH v8] " Morten Brørup
2026-07-03 15:43 ` [PATCH v9] " Morten Brørup
2026-08-13  6:56   ` Morten Brørup
2026-08-22  9:52   ` Robin Jarry
2026-08-22 10:18     ` Morten Brørup
2026-08-23  9:25 ` [PATCH v10] " Morten Brørup
2026-08-23 10:40 ` [PATCH v11] " Morten Brørup
2026-08-23 10:57 ` [PATCH v12] " Morten Brørup
2026-08-23 11:57 ` [PATCH v13] " Morten Brørup
2026-08-23 12:52 ` [PATCH v14] " Morten Brørup
2026-08-23 13:42 ` [PATCH v15] " Morten Brørup
2026-08-23 14:25 ` [PATCH v16] " Morten Brørup
2026-08-23 15:01 ` [PATCH v17] " Morten Brørup
2026-08-24 11:15   ` kirankumark
2026-08-24 14:56   ` Jerin Jacob

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260703135301.3040663-1-mb@smartsharesystems.com \
    --to=mb@smartsharesystems.com \
    --cc=dev@dpdk.org \
    --cc=jerinj@marvell.com \
    --cc=kirankumark@marvell.com \
    --cc=ndabilpuram@marvell.com \
    --cc=saeed.bishara.os@gmail.com \
    --cc=yanzhirun_163@163.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.