On Wed, Jul 15, 2026 at 11:12:59AM -0400, Kishore Padmanabha wrote:
> On Wed, Jul 15, 2026 at 5:02 AM Morten Brørup
> <[1][email protected]> wrote:
>
> > From: fengchengwen [mailto:[2][email protected]]
> > Sent: Wednesday, 15 July 2026 10.12
> >
> > On 7/15/2026 4:08 AM, Morten Brørup wrote:
> > > Hi Kishore,
> > >
> > > For your testing purposes, please follow the guidance provided
> to
> > Wisam Jaddo:
> > >
> >
> [3]https://inbox.dpdk.org/dev/98CBD80474FA8B44BF855DF32C47DC35F65964
> @smart
> > [4]server.smartshare.dk/
> >
> > We need to recompile in this case. We should try to avoid
> > recompilation.
> > I think it is necessary to adjust RTE_MEMPOOL_CACHE_MAX_SIZE to
> 768 as
> > a default configuration.
> Changing RTE_MEMPOOL_CACHE_MAX_SIZE breaks both the API and the ABI;
> so it has to be done when building locally, where API/ABI breakage
> is acceptable.
> For DPDK 26.11, where API/ABI breakage is acceptable, we can discuss
> increasing the default from 512 to a higher value. I do have some
> input to that discussion, but let's postpone it until after DPDK
> 26.07 has been released.
>
> We should increase this value to avoid performance degradation, as
> users may not realize they need to change it. We do not have do it
> right away for 26.07 release but we should it right after the
> release.
>
Out of interest, does adjusting the 50% fill/flush threshold to be a 75%
one, i.e. fill to 75% rather than 50%, flush to 25% rather than 50%, help at
all? Draft patch below, can you test it quickly, perhaps?
/Bruce
diff --git a/lib/mempool/rte_mempool.h b/lib/mempool/rte_mempool.h
index 50d958c7c6..2526a23903 100644
--- a/lib/mempool/rte_mempool.h
+++ b/lib/mempool/rte_mempool.h
@@ -1417,6 +1417,7 @@ rte_mempool_do_generic_put(struct rte_mempool *mp, void *
const *obj_table,
unsigned int n, struct rte_mempool_cache *cache)
{
void **cache_objs;
+ uint32_t quarter, flush;
/* No cache provided? */
if (unlikely(cache == NULL))
@@ -1426,30 +1427,39 @@ rte_mempool_do_generic_put(struct rte_mempool *mp, void
* const *obj_table,
RTE_MEMPOOL_CACHE_STAT_ADD(cache, put_bulk, 1);
RTE_MEMPOOL_CACHE_STAT_ADD(cache, put_objs, n);
+ /* A quarter (25%) of the cache size, computed with a shift to avoid
+ * a divide. Draining the cache down to this level on overflow leaves
+ * room for a burst of up to (size - quarter), i.e. three quarters
+ * (75%), of the cache size.
+ */
+ quarter = cache->size >> 2;
+
__rte_assume(cache->size <= RTE_MEMPOOL_CACHE_MAX_SIZE);
- __rte_assume(cache->size / 2 <= RTE_MEMPOOL_CACHE_MAX_SIZE / 2);
+ __rte_assume(quarter <= RTE_MEMPOOL_CACHE_MAX_SIZE / 2);
__rte_assume(cache->len <= RTE_MEMPOOL_CACHE_MAX_SIZE);
__rte_assume(cache->len <= cache->size);
if (likely(cache->len + n <= cache->size)) {
/* Sufficient room in the cache for the objects. */
cache_objs = &cache->objs[cache->len];
cache->len += n;
- } else if (n <= cache->size / 2) {
+ } else if (n <= cache->size - quarter) {
/*
* The number of objects is within the cache bounce buffer
limit,
* but - as detected by the comparison above - the cache has
* insufficient room for them.
* Flush the cache to the backend to make room for the objects;
- * flush (size / 2) objects from the bottom of the cache, where
- * objects are less hot, and move down the remaining objects,
which
- * are more hot, from the upper half of the cache.
+ * flush objects from the bottom of the cache, where objects are
+ * less hot, draining it down to a quarter (25%) of its size,
and
+ * move down the remaining quarter of objects, which are more
hot,
+ * from the upper part of the cache.
*/
- __rte_assume(cache->len > cache->size / 2);
- rte_mempool_ops_enqueue_bulk(mp, &cache->objs[0], cache->size /
2);
- rte_memcpy(&cache->objs[0], &cache->objs[cache->size / 2],
- sizeof(void *) * (cache->len - cache->size /
2));
- cache_objs = &cache->objs[cache->len - cache->size / 2];
- cache->len = cache->len - cache->size / 2 + n;
+ __rte_assume(cache->len > quarter);
+ flush = cache->len - quarter;
+ rte_mempool_ops_enqueue_bulk(mp, &cache->objs[0], flush);
+ rte_memcpy(&cache->objs[0], &cache->objs[flush],
+ sizeof(void *) * quarter);
+ cache_objs = &cache->objs[quarter];
+ cache->len = quarter + n;
} else {
/* The request itself is too big for the cache. */
goto driver_enqueue_stats_incremented;
@@ -1557,6 +1567,7 @@ rte_mempool_do_generic_get(struct rte_mempool *mp, void
**obj_table,
int ret;
unsigned int remaining;
uint32_t index, len;
+ uint32_t quarter, fill;
void **cache_objs;
/* No cache provided? */
@@ -1592,13 +1603,23 @@ rte_mempool_do_generic_get(struct rte_mempool *mp, void
**obj_table,
for (index = 0; index < len; index++)
*obj_table++ = *--cache_objs;
+ /* A quarter (25%) of the cache size, computed with a shift to avoid
+ * a divide; 'fill' is the complementary three quarters (75%), which
+ * is the amount fetched from the backend to fill the cache up to 75%,
+ * and also the burst limit for this bounce buffer (since the cache
+ * was just fully drained above, up to 'fill' objects can be filled
+ * and handed back to the caller in one go).
+ */
+ quarter = cache->size >> 2;
+ fill = cache->size - quarter;
+
/* Dequeue below would exceed the cache bounce buffer limit? */
- __rte_assume(cache->size / 2 <= RTE_MEMPOOL_CACHE_MAX_SIZE / 2);
- if (unlikely(remaining > cache->size / 2))
+ __rte_assume(fill <= RTE_MEMPOOL_CACHE_MAX_SIZE);
+ if (unlikely(remaining > fill))
goto driver_dequeue;
- /* Fill the cache from the backend; fetch (size / 2) objects. */
- ret = rte_mempool_ops_dequeue_bulk(mp, cache->objs, cache->size / 2);
+ /* Fill the cache from the backend, up to 75% of its size. */
+ ret = rte_mempool_ops_dequeue_bulk(mp, cache->objs, fill);
if (unlikely(ret < 0)) {
/*
* We are buffer constrained, and not able to fetch all that.
@@ -1612,11 +1633,10 @@ rte_mempool_do_generic_get(struct rte_mempool *mp, void
**obj_table,
RTE_MEMPOOL_CACHE_STAT_ADD(cache, get_success_bulk, 1);
RTE_MEMPOOL_CACHE_STAT_ADD(cache, get_success_objs, n);
- __rte_assume(cache->size / 2 <= RTE_MEMPOOL_CACHE_MAX_SIZE / 2);
- __rte_assume(remaining <= RTE_MEMPOOL_CACHE_MAX_SIZE / 2);
- __rte_assume(remaining <= cache->size / 2);
- cache_objs = &cache->objs[cache->size / 2];
- cache->len = cache->size / 2 - remaining;
+ __rte_assume(fill <= RTE_MEMPOOL_CACHE_MAX_SIZE);
+ __rte_assume(remaining <= fill);
+ cache_objs = &cache->objs[fill];
+ cache->len = fill - remaining;
for (index = 0; index < remaining; index++)
*obj_table++ = *--cache_objs;