All of lore.kernel.org
 help / color / mirror / Atom feed
From: <kirankumark@marvell.com>
To: <mb@smartsharesystems.com>
Cc: <dev@dpdk.org>, <jerinj@marvell.com>, <kirankumark@marvell.com>,
	<ndabilpuram@marvell.com>, <rjarry@redhat.com>,
	<saeed.bishara.os@gmail.com>, <yanzhirun_163@163.com>
Subject: Re: [PATCH v17] graph: add optional profiling stats
Date: Mon, 24 Aug 2026 16:45:51 +0530	[thread overview]
Message-ID: <20260824111606.779723-1-kirankumark@marvell.com> (raw)
In-Reply-To: <20260823150127.490511-1-mb@smartsharesystems.com>

On Sun, Aug 23, 2026 at 03:01:27PM +0000, Morten Brørup wrote:
> 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>
> ---

Acked-by: Kiran Kumar Kokkilagadda <kirankumark@marvell.com>

> v17:
> * Snapshot cycles as positive number, and subtract after processing.
>   (Robin Jarry)
> v16:
> * Refactored range bucketing for clarity and performance. (AI)
> v15:
> * Used the term "ranges" instead of "intervals". (AI)
> * Described the last range as "%u+" instead of "[%u;[".
>   Correct would be "[%u;+∞[", but prefer ASCII here.
> v14:
> * Changed some minor details suggested by AI.
> v13:
> * Fixed cache alignment; array should be aligned, not struct.
> * Changed some minor details suggested by AI.
> v12:
> * Multiply printed percent values by 100.0. (AI)
> * Added to release note that this feature is disabled by default. (AI)
> v11:
> * Fixed signedness comparison and copy-paste bug.
> v10:
> * Use intervals instead of point samples. (Robin Jarry)
> * Do not double-indent printf continuations.
>   Follows existing coding style in the file, and
>   avoids a long line warning from checkpatch.
> * Rebased.
>   Moved release note to 26.11 file.
> v9:
> * Fixed comment still mentioning 32 objects.
> * Moved sample size array outside loop. (AI)
> * Added release note. (AI)
> v8:
> * Added static const array as local variable, instead of indexing directly
>   into const array. (AI)
>   This also eliminates the space required between "} [idx];" weirdness.
> * Added build time configurable RTE_GRAPH_PROFILE_BURST_SIZE to replace
>   the hardcoded burst size of 32. (AI)
> 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                    |  4 ++
>  doc/guides/prog_guide/graph_lib.rst    |  5 ++
>  doc/guides/rel_notes/release_26_11.rst |  9 ++++
>  lib/graph/graph_debug.c                | 67 ++++++++++++++++++++++++++
>  lib/graph/node.c                       |  2 +
>  lib/graph/rte_graph_worker_common.h    | 57 ++++++++++++++++++++--
>  6 files changed, 141 insertions(+), 3 deletions(-)
>
> diff --git a/config/rte_config.h b/config/rte_config.h
> index 0447cdf2ad..6beee01b09 100644
> --- a/config/rte_config.h
> +++ b/config/rte_config.h
> @@ -106,6 +106,10 @@
>  /* rte_graph defines */
>  #define RTE_GRAPH_BURST_SIZE 256
>  #define RTE_LIBRTE_GRAPH_STATS 1
> +/* RTE_GRAPH_PROFILE is not set */
> +#define RTE_GRAPH_PROFILE_BURST_SMALL 8
> +#define RTE_GRAPH_PROFILE_BURST_MEDIUM 32
> +#define RTE_GRAPH_PROFILE_BURST_LARGE RTE_GRAPH_BURST_SIZE
>
>  /****** driver defines ********/
>
> diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst
> index 1c2cd1ef31..aa5faf4e82 100644
> --- a/doc/guides/prog_guide/graph_lib.rst
> +++ b/doc/guides/prog_guide/graph_lib.rst
> @@ -49,6 +49,11 @@ 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
> +  (disabled by default).
> +  Set the ``RTE_GRAPH_PROFILE_BURST_SMALL``, ``RTE_GRAPH_PROFILE_BURST_MEDIUM``,
> +  and ``RTE_GRAPH_PROFILE_BURST_LARGE`` config options to sample specific
> +  burst size ranges.
>  - Disable node statistics (using ``RTE_LIBRTE_GRAPH_STATS`` config option)
>    if not needed.
>
> diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
> index c8cc86295d..2c822b6eee 100644
> --- a/doc/guides/rel_notes/release_26_11.rst
> +++ b/doc/guides/rel_notes/release_26_11.rst
> @@ -55,6 +55,15 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
>
> +* **Added optional graph profiling statistics.**
> +
> +  Added build time configurable graph node profiling statistics via
> +  ``RTE_GRAPH_PROFILE`` in ``rte_config.h`` (disabled by default). When enabled,
> +  tracks cycles spent processing various burst size ranges per node.
> +  The edges of the ranges are build time configurable via
> +  ``RTE_GRAPH_PROFILE_BURST_SMALL``, ``RTE_GRAPH_PROFILE_BURST_MEDIUM``, and
> +  ``RTE_GRAPH_PROFILE_BURST_LARGE`` in ``rte_config.h``.
> +
>
>  Removed Items
>  -------------
> diff --git a/lib/graph/graph_debug.c b/lib/graph/graph_debug.c
> index e3b8cccdc1..a2aef9918f 100644
> --- a/lib/graph/graph_debug.c
> +++ b/lib/graph/graph_debug.c
> @@ -60,6 +60,7 @@ rte_graph_obj_dump(FILE *f, struct rte_graph *g, bool all)
>  	rte_graph_off_t off;
>  	struct rte_node *n;
>  	rte_edge_t i;
> +	uint64_t all_total_cycles = 0;
>
>  	fprintf(f, "graph <%s> @ %p\n", g->name, g);
>  	fprintf(f, "  id=%" PRIu32 "\n", g->id);
> @@ -72,6 +73,12 @@ rte_graph_obj_dump(FILE *f, struct rte_graph *g, bool all)
>  	fprintf(f, "  nodes_start=0x%" PRIx32 "\n", g->nodes_start);
>  	fprintf(f, "  cir_start=%p\n", g->cir_start);
>
> +	rte_graph_foreach_node(count, off, g, n) {
> +		if (!all && n->idx == 0)
> +			continue;
> +		all_total_cycles += n->total_cycles;
> +	}
> +
>  	rte_graph_foreach_node(count, off, g, n) {
>  		if (!all && n->idx == 0)
>  			continue;
> @@ -93,6 +100,66 @@ 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 " (%.1f%% of all nodes), avg cycles/call=%.1f\n",
> +				n->total_cycles,
> +				all_total_cycles == 0 ? 0.0 :
> +				(double)n->total_cycles / (double)all_total_cycles * 100.0,
> +				n->total_calls == 0 ? 0.0 :
> +				(double)n->total_cycles / (double)n->total_calls);
> +
> +#ifdef RTE_GRAPH_PROFILE
> +		static const uint16_t sample_sizes[] = {
> +				0, 1, 2, RTE_GRAPH_PROFILE_BURST_SMALL,
> +				RTE_GRAPH_PROFILE_BURST_MEDIUM, RTE_GRAPH_PROFILE_BURST_LARGE};
> +		static_assert(RTE_DIM(sample_sizes) == 2U + RTE_DIM(n->usage_stats),
> +				"usage_stats array size mismatch");
> +		for (unsigned int idx = 0; idx < RTE_DIM(sample_sizes); idx++) {
> +			uint64_t calls;
> +			uint64_t cycles;
> +			double objs_per_call;
> +			if (idx < 2) {
> +				calls = n->usage_stats_01[idx].calls;
> +				cycles = n->usage_stats_01[idx].cycles;
> +				objs_per_call = (double)idx;
> +				fprintf(f, "       for %u objs/call\n",
> +					idx);
> +			} else {
> +				calls = n->usage_stats[idx - 2].calls;
> +				cycles = n->usage_stats[idx - 2].cycles;
> +				objs_per_call = calls == 0 ? 0.0 :
> +						(double)n->usage_stats[idx - 2].objs /
> +						(double)calls;
> +				if (idx < RTE_DIM(sample_sizes) - 1)
> +					fprintf(f, "       for [%u;%u[ objs/call",
> +						sample_sizes[idx], sample_sizes[idx + 1]);
> +				else
> +					fprintf(f, "       for %u+ objs/call",
> +						sample_sizes[idx]);
> +				if (calls != 0)
> +					fprintf(f, ", avg %.1f objs/call\n",
> +						objs_per_call);
> +				fprintf(f, "\n");
> +			}
> +			fprintf(f, "         calls=%" PRIu64,
> +				calls);
> +			if (calls != 0) {
> +				fprintf(f, " (%.1f%% of this node)\n",
> +					n->total_calls == 0 ? 0.0 :
> +					(double)calls / (double)n->total_calls * 100.0);
> +				fprintf(f, "         cycles=%" PRIu64 " (%.1f%% of this node), avg cycles/call=%.1f",
> +					cycles,
> +					n->total_cycles == 0 ? 0.0 :
> +					(double)cycles / (double)n->total_cycles * 100.0,
> +					(double)cycles / (double)calls);
> +				if (objs_per_call != 0.0)
> +					fprintf(f, ", avg cycles/obj=%.1f",
> +						(double)cycles / (double)calls / objs_per_call);
> +			}
> +			fprintf(f, "\n");
> +		}
> +#endif /* RTE_GRAPH_PROFILE */
> +
>  		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..89c1f3dbf9 100644
> --- a/lib/graph/rte_graph_worker_common.h
> +++ b/lib/graph/rte_graph_worker_common.h
> @@ -121,6 +121,27 @@ 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 or 1 objects. */
> +	alignas(RTE_CACHE_LINE_MIN_SIZE)
> +	struct {
> +		uint64_t calls;     /**< Calls done. */
> +		uint64_t cycles;    /**< Cycles spent. */
> +	} usage_stats_01[2];
> +	/**
> +	 * Usage when this node processed N objects:
> +	 * - index 0 (micro): 2 <= N < RTE_GRAPH_PROFILE_BURST_SMALL
> +	 * - index 1 (small): RTE_GRAPH_PROFILE_BURST_SMALL <= N < RTE_GRAPH_PROFILE_BURST_MEDIUM
> +	 * - index 2 (medium): RTE_GRAPH_PROFILE_BURST_MEDIUM <= N < RTE_GRAPH_PROFILE_BURST_LARGE
> +	 * - index 3 (large): RTE_GRAPH_PROFILE_BURST_LARGE <= N
> +	 */
> +	struct {
> +		uint64_t calls;     /**< Calls done. */
> +		uint64_t cycles;    /**< Cycles spent. */
> +		uint64_t objs;      /**< Objects processed. */
> +	} usage_stats[4];
> +	/** Fast path area cache line 4. */
> +#endif
>  	__extension__ struct __rte_cache_aligned {
>  #define RTE_NODE_CTX_SZ 16
>  		union {
> @@ -148,8 +169,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 +220,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 +229,39 @@ __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() - cycles;
> +		node->total_cycles += cycles;
>  		node->total_calls++;
>  		node->total_objs += rc;
> +#ifdef RTE_GRAPH_PROFILE
> +		static_assert(RTE_GRAPH_PROFILE_BURST_SMALL >= 2,
> +			"BURST_SMALL must be >= 2");
> +		static_assert(RTE_GRAPH_PROFILE_BURST_SMALL < RTE_GRAPH_PROFILE_BURST_MEDIUM,
> +			"BURST_SMALL must be < BURST_MEDIUM");
> +		static_assert(RTE_GRAPH_PROFILE_BURST_MEDIUM < RTE_GRAPH_PROFILE_BURST_LARGE,
> +			"BURST_MEDIUM must be < BURST_LARGE");
> +		if (rc < 2) {
> +			node->usage_stats_01[rc].calls++;
> +			node->usage_stats_01[rc].cycles += cycles;
> +		} else {
> +			unsigned int index;
> +
> +			if (rc >= RTE_GRAPH_PROFILE_BURST_LARGE)
> +				index = 3;
> +			else if (rc >= RTE_GRAPH_PROFILE_BURST_MEDIUM)
> +				index = 2;
> +			else if (rc >= RTE_GRAPH_PROFILE_BURST_SMALL)
> +				index = 1;
> +			else
> +				index = 0;
> +
> +			node->usage_stats[index].calls++;
> +			node->usage_stats[index].cycles += cycles;
> +			node->usage_stats[index].objs += rc;
> +		}
> +#endif
>  	} else {
>  		node->process(graph, node, objs, node->idx);
>  	}
> --
> 2.43.0

  reply	other threads:[~2026-08-24 11:16 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 ` [PATCH v7] " Morten Brørup
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 [this message]
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=20260824111606.779723-1-kirankumark@marvell.com \
    --to=kirankumark@marvell.com \
    --cc=dev@dpdk.org \
    --cc=jerinj@marvell.com \
    --cc=mb@smartsharesystems.com \
    --cc=ndabilpuram@marvell.com \
    --cc=rjarry@redhat.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.