From: "Morten Brørup" <mb@smartsharesystems.com>
To: "Konstantin Ananyev" <konstantin.ananyev@huawei.com>, <dev@dpdk.org>
Cc: <wathsala.vithanage@arm.com>
Subject: RE: [PATCH v4 1/2] ring: make soring to always finalize its own stage
Date: Tue, 28 Apr 2026 13:54:54 +0200 [thread overview]
Message-ID: <98CBD80474FA8B44BF855DF32C47DC35F65827@smartserver.smartshare.dk> (raw)
In-Reply-To: <20260423091625.123642-2-konstantin.ananyev@huawei.com>
> From: Konstantin Ananyev [mailto:konstantin.ananyev@huawei.com]
> Sent: Thursday, 23 April 2026 11.16
>
> SORING internal finalize() function is MT-safe and can be called from
> multiple places: from it's own stage release(), also from 'acquire()'
> for next stage or even from consumer's 'dequeue().
> But calling finalize() from not its own stage release() function
> creates extra contention and might slow-down ring operations,
> especially
> for the cases when we have multiple threads doing acquire/release
> for the same stage.
> We can't compeletely avoid calling finalize() from all these multiple
> places, as it can in some rare cases break soring behavior.
> But we can make release() for given stage to invoke it always.
> That increases number of 'finalize()' operations done from 'release()'
> for current stage, and helps to minimize number of finalize() calls
> from
> other stages, which in turn, help to reduce the contention.
> According to the soring_stress_autotest, for multiple workers (8+)
> it reduces number of cycles spent by 1.5x-1.8x factor.
> For l3fwd-like workload it improves things by ~20%.
> For small number of workers, I didn't observe any serious change.
> Note that it doesn't introduce any changes in functionality provided.
>
> Signed-off-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>
Good idea.
Not peeking into the tail to determine if finalize() might be omitted also makes release() cleaner.
Removing an optimization that was not really an optimization. :-)
Acked-by: Morten Brørup <mb@smartsharesystems.com>
> ---
> lib/ring/soring.c | 33 +++++++++++++++------------------
> 1 file changed, 15 insertions(+), 18 deletions(-)
>
> diff --git a/lib/ring/soring.c b/lib/ring/soring.c
> index 3b90521bdb..4bc2321fb5 100644
> --- a/lib/ring/soring.c
> +++ b/lib/ring/soring.c
> @@ -37,24 +37,24 @@
> * plus current stage index).
> * 'release()' extracts old head value from provided ftoken and checks
> that
> * corresponding 'state[]' contains expected values(mostly for sanity
> - * purposes).
> - * Then it marks this state[] with 'SORING_ST_FINISH' flag to indicate
> - * that given subset of objects was released.
> - * After that, it checks does old head value equals to current tail
> value?
> - * If yes, then it performs 'finalize()' operation, otherwise
> 'release()'
> - * just returns (without spinning on stage tail value).
> - * As updated state[] is shared by all threads, some other thread can
> do
> - * 'finalize()' for given stage.
> - * That allows 'release()' to avoid excessive waits on the tail value.
> + * purposes). Then it marks this state[] with 'SORING_ST_FINISH' flag
> to
> + * indicate that given subset of objects was released.
> + * After that, it calls 'finalize()'.
> * Main purpose of 'finalize()' operation is to walk through 'state[]'
> * from current stage tail up to its head, check state[] and move
> stage tail
> * through elements that already are in SORING_ST_FINISH state.
> * Along with that, corresponding state[] values are reset to zero.
> - * Note that 'finalize()' for given stage can be done from multiple
> places:
> + * Note that updated state[] is shared by all threads, so
> + * 'finalize()' for given stage can be done from multiple places:
> * 'release()' for that stage or from 'acquire()' for next stage
> * even from consumer's 'dequeue()' - in case given stage is the last
> one.
> * So 'finalize()' has to be MT-safe and inside it we have to
> - * guarantee that only one thread will update state[] and stage's tail
> values.
> + * guarantee that only one thread at a time will update state[] and
> + * stage's tail values (sort of critical-section).
> + * When multiple threads trying to do finalize() for the same stage,
> + * simultaneously one thread will win the race and do all the pending
> + * updates, while others will simply return (kind of try-lock
> scenario).
> + * That allows 'release()' to avoid excessive waits on the tail value.
> */
>
> #include "soring.h"
> @@ -442,7 +442,7 @@ static __rte_always_inline void
> soring_release(struct rte_soring *r, const void *objs,
> const void *meta, uint32_t stage, uint32_t n, uint32_t ftoken)
> {
> - uint32_t idx, pos, tail;
> + uint32_t idx, pos;
> struct soring_stage *stg;
> union soring_state st;
>
> @@ -479,12 +479,9 @@ soring_release(struct rte_soring *r, const void
> *objs,
> rte_atomic_store_explicit(&r->state[idx].raw, st.raw,
> rte_memory_order_relaxed);
>
> - /* try to do finalize(), if appropriate */
> - tail = rte_atomic_load_explicit(&stg->sht.tail.pos,
> - rte_memory_order_relaxed);
> - if (tail == pos)
> - __rte_soring_stage_finalize(&stg->sht, stage, r->state, r-
> >mask,
> - r->capacity);
> + /* now, try to do finalize() */
> + __rte_soring_stage_finalize(&stg->sht, stage, r->state, r->mask,
> + r->capacity);
> }
>
> /*
> --
> 2.51.0
next prev parent reply other threads:[~2026-04-28 11:54 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-15 17:16 [PATCH v1 0/2] few improvemnts for SORING lib Konstantin Ananyev
2026-04-15 17:16 ` [PATCH v1 1/2] ring: make soring to finalize its own stage only Konstantin Ananyev
2026-04-15 17:16 ` [PATCH v1 2/2] ring: introduce peek API for soring Konstantin Ananyev
2026-04-16 19:14 ` [PATCH v2 0/2] few improvemnts for SORING lib Konstantin Ananyev
2026-04-16 19:14 ` [PATCH v2 1/2] ring: make soring to finalize its own stage only Konstantin Ananyev
2026-04-16 19:14 ` [PATCH v2 2/2] ring: introduce peek API for soring Konstantin Ananyev
2026-04-17 21:23 ` [PATCH v3 0/2] few improvemnts for SORING lib Konstantin Ananyev
2026-04-17 21:23 ` [PATCH v3 1/2] ring: make soring to finalize its own stage only Konstantin Ananyev
2026-04-17 21:23 ` [PATCH v3 2/2] ring: introduce peek API for soring Konstantin Ananyev
2026-04-18 3:28 ` [PATCH v3 0/2] few improvemnts for SORING lib Stephen Hemminger
2026-04-23 9:16 ` [PATCH v4 " Konstantin Ananyev
2026-04-23 9:16 ` [PATCH v4 1/2] ring: make soring to always finalize its own stage Konstantin Ananyev
2026-04-28 11:54 ` Morten Brørup [this message]
2026-04-23 9:16 ` [PATCH v4 2/2] ring: introduce peek API for soring Konstantin Ananyev
2026-04-28 12:56 ` Morten Brørup
2026-05-05 15:45 ` Konstantin Ananyev
2026-04-29 15:57 ` [PATCH v4 0/2] few improvemnts for SORING lib Stephen Hemminger
2026-05-05 15:47 ` [PATCH v5 " Konstantin Ananyev
2026-05-05 15:47 ` [PATCH v5 1/2] ring: make soring to always finalize its own stage Konstantin Ananyev
2026-05-05 15:47 ` [PATCH v5 2/2] ring: introduce peek API for soring Konstantin Ananyev
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=98CBD80474FA8B44BF855DF32C47DC35F65827@smartserver.smartshare.dk \
--to=mb@smartsharesystems.com \
--cc=dev@dpdk.org \
--cc=konstantin.ananyev@huawei.com \
--cc=wathsala.vithanage@arm.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox