* [PATCH 0/7] app/test: make perf tests usable on wider range of systems
@ 2026-05-29 17:10 Stephen Hemminger
2026-05-29 17:10 ` [PATCH 1/7] app/test/reciprocal_division: make it a fast test Stephen Hemminger
` (7 more replies)
0 siblings, 8 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-05-29 17:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
Today' side quest is fixing the perftests to run on my machines.
Several of the perf/autotests assume server-class machines: they run for
billions of iterations, or size hugepage allocations by total lcore count,
which makes them time out or fail to allocate on smaller systems and on
machines with high core counts but modest memory.
This series trims runtime and memory use without losing meaningful test
coverage, and reports resource shortfalls as skips rather than failures.
Stephen Hemminger (7):
app/test/reciprocal_division: make it a fast test
app/test/reciprocal_division_perf: reduce test time
app/test/mempool_perf: size mempool by tested cores
app/test/mempool_perf: drop constant-values replay
app/test/mempool_perf: scale down for high core counts
app/test/test_rcu_qsbr_perf: call quiescent more often
app/test/test_pmd_perf: skip if no device available
app/test/test_mempool_perf.c | 84 +++----
app/test/test_pmd_perf.c | 2 +-
app/test/test_rcu_qsbr_perf.c | 3 +-
app/test/test_reciprocal_division.c | 279 +++++++++++++----------
app/test/test_reciprocal_division_perf.c | 4 +-
5 files changed, 196 insertions(+), 176 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/7] app/test/reciprocal_division: make it a fast test
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
@ 2026-05-29 17:10 ` Stephen Hemminger
2026-05-29 17:10 ` [PATCH 2/7] app/test/reciprocal_division_perf: reduce test time Stephen Hemminger
` (6 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-05-29 17:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
This test is useful to have in CI, but the iteration values
were too large to make it usable as a fast test.
Redo the test with checks around boundary values and
use unit test framework for sub tests.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_reciprocal_division.c | 279 ++++++++++++++++------------
1 file changed, 157 insertions(+), 122 deletions(-)
diff --git a/app/test/test_reciprocal_division.c b/app/test/test_reciprocal_division.c
index 3d0736d8dd..80f8561523 100644
--- a/app/test/test_reciprocal_division.c
+++ b/app/test/test_reciprocal_division.c
@@ -5,162 +5,197 @@
#include "test.h"
#include <stdio.h>
-#include <unistd.h>
#include <inttypes.h>
#include <rte_common.h>
-#include <rte_cycles.h>
#include <rte_random.h>
#include <rte_reciprocal.h>
-#define MAX_ITERATIONS (1ULL << 32)
-#define DIVIDE_ITER (100)
+#define MAX_ITERATIONS (1ULL << 20)
+#define DIVISORS_RANDOM 64
static int
-test_reciprocal(void)
+test_u32_divide(uint32_t a, uint32_t d, struct rte_reciprocal r)
{
- int result = 0;
- uint32_t divisor_u32 = 0;
- uint32_t dividend_u32;
- uint32_t nresult_u32;
- uint32_t rresult_u32;
- uint64_t i, j;
- uint64_t divisor_u64 = 0;
- uint64_t dividend_u64;
- uint64_t nresult_u64;
- uint64_t rresult_u64;
- struct rte_reciprocal reci_u32 = {0};
- struct rte_reciprocal_u64 reci_u64 = {0};
-
- printf("Validating unsigned 32bit division.\n");
- for (i = 0; i < MAX_ITERATIONS; i++) {
- /* Change divisor every DIVIDE_ITER iterations. */
- if (i % DIVIDE_ITER == 0) {
- divisor_u32 = rte_rand();
- reci_u32 = rte_reciprocal_value(divisor_u32);
- }
-
- dividend_u32 = rte_rand();
- nresult_u32 = dividend_u32 / divisor_u32;
- rresult_u32 = rte_reciprocal_divide(dividend_u32,
- reci_u32);
- if (nresult_u32 != rresult_u32) {
- printf("Division failed, %"PRIu32"/%"PRIu32" = "
- "expected %"PRIu32" result %"PRIu32"\n",
- dividend_u32, divisor_u32,
- nresult_u32, rresult_u32);
- result = 1;
- break;
- }
- }
+ uint32_t expected = a / d;
+ uint32_t result = rte_reciprocal_divide(a, r);
- printf("Validating unsigned 64bit division.\n");
- for (i = 0; i < MAX_ITERATIONS; i++) {
- /* Change divisor every DIVIDE_ITER iterations. */
- if (i % DIVIDE_ITER == 0) {
- divisor_u64 = rte_rand();
- reci_u64 = rte_reciprocal_value_u64(divisor_u64);
- }
+ TEST_ASSERT_EQUAL(expected, result,
+ "%"PRIu32"/%"PRIu32" expected %"PRIu32" got %"PRIu32,
+ a, d, expected, result);
+ return 0;
+}
- dividend_u64 = rte_rand();
- nresult_u64 = dividend_u64 / divisor_u64;
- rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
- &reci_u64);
- if (nresult_u64 != rresult_u64) {
- printf("Division failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- break;
+static int
+test_reciprocal_u32(void)
+{
+ const uint32_t edge_div_u32[] = {
+ 1, 2, 3, 7, 0x7fffffff, 0x80000000, 0xfffffffe, UINT32_MAX,
+ };
+ unsigned int n_div = RTE_DIM(edge_div_u32) + DIVISORS_RANDOM;
+
+ for (unsigned int di = 0; di < n_div; di++) {
+ uint32_t d;
+ if (di < RTE_DIM(edge_div_u32))
+ d = edge_div_u32[di]; /* Make sure and test the edge cases */
+ else
+ d = rte_rand_max(UINT32_MAX - 1) + 1;
+
+ struct rte_reciprocal r = rte_reciprocal_value(d);
+ uint32_t qmax = UINT32_MAX / d; /* largest q with q*d <= UINT32_MAX */
+ if (d != 1)
+ qmax++;
+
+ for (unsigned int k = 0; k < MAX_ITERATIONS; k++) {
+ uint32_t q = rte_rand_max(qmax);
+ uint32_t val = q * d; /* fits in u32 */
+
+ /* Check around the value.
+ * Under and overflow of 32 bit value are fine here.
+ */
+ if (test_u32_divide(val - 1, d, r) < 0 ||
+ test_u32_divide(val, d, r) < 0 ||
+ test_u32_divide(val + 1, d, r) < 0)
+ return -1;
}
}
+ return TEST_SUCCESS;
+}
- printf("Validating unsigned 64bit division with 32bit divisor.\n");
- for (i = 0; i < MAX_ITERATIONS; i++) {
- /* Change divisor every DIVIDE_ITER iterations. */
- if (i % DIVIDE_ITER == 0) {
- divisor_u64 = rte_rand() >> 32;
- reci_u64 = rte_reciprocal_value_u64(divisor_u64);
- }
+static int
+test_u64_divide(uint64_t a, uint64_t d, const struct rte_reciprocal_u64 *r)
+{
+ uint64_t expected = a / d;
+ uint64_t result = rte_reciprocal_divide_u64(a, r);
+
+ TEST_ASSERT_EQUAL(expected, result,
+ "%"PRIu64"/%"PRIu64" expected %"PRIu64" got %"PRIu64,
+ a, d, expected, result);
+ return 0;
+}
- dividend_u64 = rte_rand();
- nresult_u64 = dividend_u64 / divisor_u64;
- rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
- &reci_u64);
+static int
+test_reciprocal_u64(void)
+{
+ const uint64_t edge_div_u64[] = {
+ 1, 2, 3, 7, 0x7fffffff, 0x80000000, 0xfffffffe, UINT64_MAX,
+ };
+ unsigned int n_div = RTE_DIM(edge_div_u64) + DIVISORS_RANDOM;
+
+ for (unsigned int di = 0; di < n_div; di++) {
+ uint64_t d;
+ if (di < RTE_DIM(edge_div_u64))
+ d = edge_div_u64[di];
+ else
+ d = rte_rand_max(UINT64_MAX - 1) + 1;
+
+ struct rte_reciprocal_u64 r = rte_reciprocal_value_u64(d);
+ uint64_t qmax = UINT64_MAX / d; /* largest q with q*d <= UINT64_MAX */
+ if (d != 1)
+ ++qmax;
+
+ for (unsigned int k = 0; k < MAX_ITERATIONS; k++) {
+ uint64_t q = rte_rand_max(qmax);
+ uint64_t val = q * d;
+
+ if (test_u64_divide(val - 1, d, &r) < 0 ||
+ test_u64_divide(val, d, &r) < 0 ||
+ test_u64_divide(val + 1, d, &r) < 0)
+ return -1;
- if (nresult_u64 != rresult_u64) {
- printf("Division failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- break;
}
}
+ return TEST_SUCCESS;
+}
- printf("Validating division by power of 2.\n");
- for (i = 0; i < 32; i++) {
- divisor_u64 = 1ull << i;
- reci_u64 = rte_reciprocal_value_u64(divisor_u64);
- reci_u32 = rte_reciprocal_value((uint32_t)divisor_u64);
+static int
+test_reciprocal_u64_small(void)
+{
+ /* 64-bit division with a 32-bit-range divisor */
+ uint64_t divisor_u64 = (rte_rand() >> 32) | 1;
+ struct rte_reciprocal_u64 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+
+ for (unsigned int i = 0; i < MAX_ITERATIONS; i++) {
+ uint64_t dividend_u64 = rte_rand();
+ uint64_t nresult_u64 = dividend_u64 / divisor_u64;
+ uint64_t rresult_u64 = rte_reciprocal_divide_u64(dividend_u64, &reci_u64);
+
+ TEST_ASSERT_EQUAL(nresult_u64, rresult_u64,
+ "%"PRIu64"/%"PRIu64" = expected %"PRIu64" got %"PRIu64,
+ dividend_u64, divisor_u64, nresult_u64, rresult_u64);
+ }
- for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
- dividend_u64 = rte_rand();
+ return TEST_SUCCESS;
+}
- nresult_u64 = dividend_u64 / divisor_u64;
- rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+static int
+test_reciprocal_pow2(void)
+{
+ for (unsigned int i = 0; i < 32; i++) {
+ uint64_t divisor_u64 = 1ULL << i;
+ struct rte_reciprocal_u64 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ struct rte_reciprocal reci_u32 = rte_reciprocal_value((uint32_t)divisor_u64);
+
+ for (unsigned int j = 0; j < MAX_ITERATIONS >> 4; j++) {
+ uint64_t dividend_u64 = rte_rand();
+ uint64_t nresult_u64 = dividend_u64 / divisor_u64;
+ uint64_t rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
&reci_u64);
- if (nresult_u64 != rresult_u64) {
- printf(
- "Division 64 failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- }
-
- nresult_u32 = (dividend_u64 >> 32) / divisor_u64;
- rresult_u32 = rte_reciprocal_divide(
+ TEST_ASSERT_EQUAL(nresult_u64, rresult_u64,
+ "u64 %"PRIu64"/%"PRIu64" = expected %"PRIu64" got %"PRIu64,
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
+
+ uint32_t nresult_u32 = (dividend_u64 >> 32) / divisor_u64;
+ uint32_t rresult_u32 = rte_reciprocal_divide(
(dividend_u64 >> 32), reci_u32);
- if (nresult_u32 != rresult_u32) {
- printf(
- "Division 32 failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64 >> 32, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- break;
- }
+ TEST_ASSERT_EQUAL(nresult_u32, rresult_u32,
+ "u32 %"PRIu64"/%"PRIu64" = expected %"PRIu32" got %"PRIu32,
+ dividend_u64 >> 32, divisor_u64,
+ nresult_u32, rresult_u32);
}
}
- for (; i < 64; i++) {
- divisor_u64 = 1ull << i;
- reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ for (unsigned int i = 32; i < 64; i++) {
+ uint64_t divisor_u64 = 1ULL << i;
+ struct rte_reciprocal_u64 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
- for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
- dividend_u64 = rte_rand();
-
- nresult_u64 = dividend_u64 / divisor_u64;
- rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ for (unsigned int j = 0; j < MAX_ITERATIONS >> 4; j++) {
+ uint64_t dividend_u64 = rte_rand();
+ uint64_t nresult_u64 = dividend_u64 / divisor_u64;
+ uint64_t rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
&reci_u64);
- if (nresult_u64 != rresult_u64) {
- printf("Division failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- break;
- }
+ TEST_ASSERT_EQUAL(nresult_u64, rresult_u64,
+ "u64 %"PRIu64"/%"PRIu64" = expected %"PRIu64" got %"PRIu64,
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
}
}
- return result;
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite reciprocal_tests = {
+ .suite_name = "reciprocal division autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_reciprocal_u32),
+ TEST_CASE(test_reciprocal_u64),
+ TEST_CASE(test_reciprocal_u64_small),
+ TEST_CASE(test_reciprocal_pow2),
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_reciprocal(void)
+{
+ return unit_test_suite_runner(&reciprocal_tests);
}
-REGISTER_PERF_TEST(reciprocal_division, test_reciprocal);
+REGISTER_FAST_TEST(reciprocal_division_autotest, NOHUGE_OK, ASAN_OK, test_reciprocal);
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/7] app/test/reciprocal_division_perf: reduce test time
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
2026-05-29 17:10 ` [PATCH 1/7] app/test/reciprocal_division: make it a fast test Stephen Hemminger
@ 2026-05-29 17:10 ` Stephen Hemminger
2026-05-29 17:10 ` [PATCH 3/7] app/test/mempool_perf: size mempool by tested cores Stephen Hemminger
` (5 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-05-29 17:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
The test time was excessively long it does not need to go
for 2^32 iterations.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_reciprocal_division_perf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/test/test_reciprocal_division_perf.c b/app/test/test_reciprocal_division_perf.c
index 6c8afc6e36..046a77f5f2 100644
--- a/app/test/test_reciprocal_division_perf.c
+++ b/app/test/test_reciprocal_division_perf.c
@@ -13,8 +13,8 @@
#include <rte_random.h>
#include <rte_reciprocal.h>
-#define MAX_ITERATIONS (1ULL << 32)
-#define DIVIDE_ITER (1ULL << 28)
+#define MAX_ITERATIONS (1ULL << 24)
+#define DIVIDE_ITER (1ULL << 10)
static int
test_reciprocal_division_perf(void)
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 3/7] app/test/mempool_perf: size mempool by tested cores
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
2026-05-29 17:10 ` [PATCH 1/7] app/test/reciprocal_division: make it a fast test Stephen Hemminger
2026-05-29 17:10 ` [PATCH 2/7] app/test/reciprocal_division_perf: reduce test time Stephen Hemminger
@ 2026-05-29 17:10 ` Stephen Hemminger
2026-06-01 8:12 ` Andrew Rybchenko
2026-05-29 17:10 ` [PATCH 4/7] app/test/mempool_perf: drop constant-values replay Stephen Hemminger
` (4 subsequent siblings)
7 siblings, 1 reply; 21+ messages in thread
From: Stephen Hemminger @ 2026-05-29 17:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Andrew Rybchenko, Morten Brørup
The mempool size is computed from rte_lcore_count() so on systems
with many lcores the test requires multiple GB of hugepages even
for the single-core and dual-core variants. On a 20 lcore system
with 2 GB of hugepages the test fails with:
cannot populate ring_mp_mc mempool
Test Failed
Size the four mempools by the number of cores actually exercised.
Return TEST_SKIPPED rather than -1 when allocation or populate of
a mempool fails, so insufficient memory is reported as a skip and
not as a test failure. Propagate the skip through the combined
mempool_perf_autotest wrapper.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_mempool_perf.c | 44 +++++++++++++++++++-----------------
1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/app/test/test_mempool_perf.c b/app/test/test_mempool_perf.c
index e164eca788..19591ad0c9 100644
--- a/app/test/test_mempool_perf.c
+++ b/app/test/test_mempool_perf.c
@@ -84,7 +84,6 @@
#define MEMPOOL_ELT_SIZE 2048
#define MAX_KEEP 32768
#define N (128 * MAX_KEEP)
-#define MEMPOOL_SIZE ((rte_lcore_count()*(MAX_KEEP+RTE_MEMPOOL_CACHE_MAX_SIZE*2))-1)
/* Number of pointers fitting into one cache line. */
#define CACHE_LINE_BURST (RTE_CACHE_LINE_SIZE / sizeof(uintptr_t))
@@ -330,7 +329,7 @@ launch_cores(struct rte_mempool *mp, unsigned int cores)
n_get_bulk, n_put_bulk,
use_constant_values);
- if (rte_mempool_avail_count(mp) != MEMPOOL_SIZE) {
+ if (rte_mempool_avail_count(mp) != mp->size) {
printf("mempool is not full\n");
return -1;
}
@@ -449,22 +448,25 @@ do_all_mempool_perf_tests(unsigned int cores)
const char *mp_cache_ops;
const char *mp_nocache_ops;
const char *default_pool_ops;
+ unsigned int mempool_size = cores *
+ (MAX_KEEP + RTE_MEMPOOL_CACHE_MAX_SIZE * 2) - 1;
int ret = -1;
/* create a mempool (without cache) */
- mp_nocache = rte_mempool_create("perf_test_nocache", MEMPOOL_SIZE,
+ mp_nocache = rte_mempool_create("perf_test_nocache", mempool_size,
MEMPOOL_ELT_SIZE, 0, 0,
NULL, NULL,
my_obj_init, NULL,
SOCKET_ID_ANY, 0);
if (mp_nocache == NULL) {
printf("cannot allocate mempool (without cache)\n");
+ ret = TEST_SKIPPED;
goto err;
}
mp_nocache_ops = rte_mempool_get_ops(mp_nocache->ops_index)->name;
/* create a mempool (with cache) */
- mp_cache = rte_mempool_create("perf_test_cache", MEMPOOL_SIZE,
+ mp_cache = rte_mempool_create("perf_test_cache", mempool_size,
MEMPOOL_ELT_SIZE,
RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
NULL, NULL,
@@ -472,6 +474,7 @@ do_all_mempool_perf_tests(unsigned int cores)
SOCKET_ID_ANY, 0);
if (mp_cache == NULL) {
printf("cannot allocate mempool (with cache)\n");
+ ret = TEST_SKIPPED;
goto err;
}
mp_cache_ops = rte_mempool_get_ops(mp_cache->ops_index)->name;
@@ -480,12 +483,13 @@ do_all_mempool_perf_tests(unsigned int cores)
/* Create a mempool (without cache) based on Default handler */
default_pool_nocache = rte_mempool_create_empty("default_pool_nocache",
- MEMPOOL_SIZE,
+ mempool_size,
MEMPOOL_ELT_SIZE,
0, 0,
SOCKET_ID_ANY, 0);
if (default_pool_nocache == NULL) {
printf("cannot allocate %s mempool (without cache)\n", default_pool_ops);
+ ret = TEST_SKIPPED;
goto err;
}
if (rte_mempool_set_ops_byname(default_pool_nocache, default_pool_ops, NULL) < 0) {
@@ -494,18 +498,20 @@ do_all_mempool_perf_tests(unsigned int cores)
}
if (rte_mempool_populate_default(default_pool_nocache) < 0) {
printf("cannot populate %s mempool\n", default_pool_ops);
+ ret = TEST_SKIPPED;
goto err;
}
rte_mempool_obj_iter(default_pool_nocache, my_obj_init, NULL);
/* Create a mempool (with cache) based on Default handler */
default_pool_cache = rte_mempool_create_empty("default_pool_cache",
- MEMPOOL_SIZE,
+ mempool_size,
MEMPOOL_ELT_SIZE,
RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
SOCKET_ID_ANY, 0);
if (default_pool_cache == NULL) {
printf("cannot allocate %s mempool (with cache)\n", default_pool_ops);
+ ret = TEST_SKIPPED;
goto err;
}
if (rte_mempool_set_ops_byname(default_pool_cache, default_pool_ops, NULL) < 0) {
@@ -514,6 +520,7 @@ do_all_mempool_perf_tests(unsigned int cores)
}
if (rte_mempool_populate_default(default_pool_cache) < 0) {
printf("cannot populate %s mempool\n", default_pool_ops);
+ ret = TEST_SKIPPED;
goto err;
}
rte_mempool_obj_iter(default_pool_cache, my_obj_init, NULL);
@@ -584,27 +591,22 @@ test_mempool_perf_allcores(void)
static int
test_mempool_perf(void)
{
- int ret = -1;
+ int ret;
/* performance test with 1, 2 and max cores */
- if (do_all_mempool_perf_tests(1) < 0)
- goto err;
+ ret = do_all_mempool_perf_tests(1);
+ if (ret != 0)
+ return ret;
if (rte_lcore_count() == 1)
- goto done;
+ return 0;
- if (do_all_mempool_perf_tests(2) < 0)
- goto err;
+ ret = do_all_mempool_perf_tests(2);
+ if (ret != 0)
+ return ret;
if (rte_lcore_count() == 2)
- goto done;
-
- if (do_all_mempool_perf_tests(rte_lcore_count()) < 0)
- goto err;
+ return 0;
-done:
- ret = 0;
-
-err:
- return ret;
+ return do_all_mempool_perf_tests(rte_lcore_count());
}
REGISTER_PERF_TEST(mempool_perf_autotest, test_mempool_perf);
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 4/7] app/test/mempool_perf: drop constant-values replay
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
` (2 preceding siblings ...)
2026-05-29 17:10 ` [PATCH 3/7] app/test/mempool_perf: size mempool by tested cores Stephen Hemminger
@ 2026-05-29 17:10 ` Stephen Hemminger
2026-06-01 8:34 ` Andrew Rybchenko
2026-05-29 17:10 ` [PATCH 5/7] app/test/mempool_perf: scale down for high core counts Stephen Hemminger
` (3 subsequent siblings)
7 siblings, 1 reply; 21+ messages in thread
From: Stephen Hemminger @ 2026-05-29 17:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Andrew Rybchenko, Morten Brørup
The second nested matrix replays each (n_get_bulk == n_put_bulk)
point with use_constant_values=1 to exercise the compile-time
constant bulk-size paths in test_loop(). This roughly doubles the
work for the get/put diagonal at every n_keep without adding new
signal: the cycles/op result for a constant bulk is interesting in
isolated inlining studies, not in routine regression sweeps.
Drop the replay. The use_constant_values switch and its branches
in test_loop() are retained for now since they are exercised by
hand in any local benchmarking.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_mempool_perf.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/app/test/test_mempool_perf.c b/app/test/test_mempool_perf.c
index 19591ad0c9..dd2f0bbaca 100644
--- a/app/test/test_mempool_perf.c
+++ b/app/test/test_mempool_perf.c
@@ -423,14 +423,6 @@ do_one_mempool_test(struct rte_mempool *mp, unsigned int cores, int external_cac
ret = launch_cores(mp, cores);
if (ret < 0)
return -1;
-
- /* replay test with constant values */
- if (n_get_bulk == n_put_bulk) {
- use_constant_values = 1;
- ret = launch_cores(mp, cores);
- if (ret < 0)
- return -1;
- }
}
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 5/7] app/test/mempool_perf: scale down for high core counts
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
` (3 preceding siblings ...)
2026-05-29 17:10 ` [PATCH 4/7] app/test/mempool_perf: drop constant-values replay Stephen Hemminger
@ 2026-05-29 17:10 ` Stephen Hemminger
2026-06-01 8:42 ` Andrew Rybchenko
2026-06-01 12:58 ` Morten Brørup
2026-05-29 17:10 ` [PATCH 6/7] app/test/test_rcu_qsbr_perf: call quiescent more often Stephen Hemminger
` (2 subsequent siblings)
7 siblings, 2 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-05-29 17:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Andrew Rybchenko, Morten Brørup
On a 32-core system the test matrix runs the cartesian product of
4 mempools, 3 core-count configurations and ~340 (n_keep, bulk)
points at TIME_S=1 second each: about 67 minutes total, well past
the 10 minute perf-test timeout.
Two reductions, no loss of meaningful signal:
1. Per-point duration: 1 second -> 200 ms. Each point currently
collects 10^5-10^6 mempool ops; 200 ms still yields >10^4
samples, well above the noise floor for a cycles-per-op average.
2. Matrix trim: drop adjacent bulk and n_keep points that don't
produce regime changes. Retained set covers the boundaries
that matter: 1, 4, cache-line burst (8), typical packet burst
(32) and cache size (RTE_MEMPOOL_CACHE_MAX_SIZE = 512) for bulk;
32 (fits in cache), 512 (= cache size) and 32768 (far exceeds
cache) for n_keep.
Combined effect: ~10x runtime reduction.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_mempool_perf.c | 32 ++++++++++++--------------------
1 file changed, 12 insertions(+), 20 deletions(-)
diff --git a/app/test/test_mempool_perf.c b/app/test/test_mempool_perf.c
index dd2f0bbaca..6801812a8d 100644
--- a/app/test/test_mempool_perf.c
+++ b/app/test/test_mempool_perf.c
@@ -61,26 +61,21 @@
*
* - Pseudorandom max bulk size (*n_max_bulk*)
*
- * - Max bulk from CACHE_LINE_BURST to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE,
- * where CACHE_LINE_BURST is the number of pointers fitting into one CPU cache line.
+ * - Max bulk: CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE,
+ * where CACHE_LINE_BURST is the number of pointers fitting into
+ * one CPU cache line.
*
* - Fixed bulk size (*n_get_bulk*, *n_put_bulk*)
*
- * - Bulk get from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE
- * - Bulk put from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE
- * - Bulk get and put from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE, compile time constant
+ * - Bulk get: 1, 4, CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE
+ * - Bulk put: 1, 4, CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE
*
* - Number of kept objects (*n_keep*)
*
- * - 32
- * - 128
- * - 512
- * - 2048
- * - 8192
- * - 32768
+ * - 32, 512, 32768
*/
-#define TIME_S 1
+#define TIME_MS 200
#define MEMPOOL_ELT_SIZE 2048
#define MAX_KEEP 32768
#define N (128 * MAX_KEEP)
@@ -257,7 +252,7 @@ per_lcore_mempool_test(void *arg)
start_cycles = rte_get_timer_cycles();
- while (time_diff/hz < TIME_S) {
+ while (time_diff < hz * TIME_MS / 1000) {
if (n_max_bulk != 0)
ret = test_loop_random(mp, cache, n_keep, n_max_bulk);
else if (!use_constant_values)
@@ -376,13 +371,10 @@ launch_cores(struct rte_mempool *mp, unsigned int cores)
static int
do_one_mempool_test(struct rte_mempool *mp, unsigned int cores, int external_cache)
{
- unsigned int bulk_tab_max[] = { CACHE_LINE_BURST, 32, 64, 128, 256,
- RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
- unsigned int bulk_tab_get[] = { 1, 4, CACHE_LINE_BURST, 32, 64, 128, 256,
- RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
- unsigned int bulk_tab_put[] = { 1, 4, CACHE_LINE_BURST, 32, 64, 128, 256,
- RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
- unsigned int keep_tab[] = { 32, 128, 512, 2048, 8192, 32768, 0 };
+ unsigned int bulk_tab_max[] = { CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
+ unsigned int bulk_tab_get[] = { 1, 4, CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
+ unsigned int bulk_tab_put[] = { 1, 4, CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
+ unsigned int keep_tab[] = { 32, 512, 32768, 0 };
unsigned int *max_bulk_ptr;
unsigned int *get_bulk_ptr;
unsigned int *put_bulk_ptr;
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 6/7] app/test/test_rcu_qsbr_perf: call quiescent more often
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
` (4 preceding siblings ...)
2026-05-29 17:10 ` [PATCH 5/7] app/test/mempool_perf: scale down for high core counts Stephen Hemminger
@ 2026-05-29 17:10 ` Stephen Hemminger
2026-05-29 17:11 ` [PATCH 7/7] app/test/test_pmd_perf: skip if no device available Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems Stephen Hemminger
7 siblings, 0 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-05-29 17:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Honnappa Nagarahalli
The performance test would generate large backlog of quiescent
actions which caused test to take excessively long time.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_rcu_qsbr_perf.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/app/test/test_rcu_qsbr_perf.c b/app/test/test_rcu_qsbr_perf.c
index bdffd64e60..8768a9ce1a 100644
--- a/app/test/test_rcu_qsbr_perf.c
+++ b/app/test/test_rcu_qsbr_perf.c
@@ -313,9 +313,8 @@ test_rcu_qsbr_hash_reader(void *arg)
pdata[thread_id]++;
}
rte_rcu_qsbr_unlock(temp, thread_id);
+ rte_rcu_qsbr_quiescent(temp, thread_id);
}
- /* Update quiescent state counter */
- rte_rcu_qsbr_quiescent(temp, thread_id);
rte_rcu_qsbr_thread_offline(temp, thread_id);
loop_cnt++;
} while (!writer_done);
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 7/7] app/test/test_pmd_perf: skip if no device available
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
` (5 preceding siblings ...)
2026-05-29 17:10 ` [PATCH 6/7] app/test/test_rcu_qsbr_perf: call quiescent more often Stephen Hemminger
@ 2026-05-29 17:11 ` Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems Stephen Hemminger
7 siblings, 0 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-05-29 17:11 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
Rather than exiting with FAILURE the test should exit
with SKIPPED status if it can't find a device to attach to.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_pmd_perf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/test/test_pmd_perf.c b/app/test/test_pmd_perf.c
index 995b0a6f20..8eff0a1223 100644
--- a/app/test/test_pmd_perf.c
+++ b/app/test/test_pmd_perf.c
@@ -691,7 +691,7 @@ test_pmd_perf(void)
if (nb_ports < NB_ETHPORTS_USED) {
printf("At least %u port(s) used for perf. test\n",
NB_ETHPORTS_USED);
- return -1;
+ return TEST_SKIPPED;
}
nb_lcores = rte_lcore_count();
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 3/7] app/test/mempool_perf: size mempool by tested cores
2026-05-29 17:10 ` [PATCH 3/7] app/test/mempool_perf: size mempool by tested cores Stephen Hemminger
@ 2026-06-01 8:12 ` Andrew Rybchenko
2026-06-01 12:22 ` Morten Brørup
0 siblings, 1 reply; 21+ messages in thread
From: Andrew Rybchenko @ 2026-06-01 8:12 UTC (permalink / raw)
To: Stephen Hemminger, dev; +Cc: Morten Brørup
On 5/29/26 8:10 PM, Stephen Hemminger wrote:
> The mempool size is computed from rte_lcore_count() so on systems
> with many lcores the test requires multiple GB of hugepages even
> for the single-core and dual-core variants. On a 20 lcore system
> with 2 GB of hugepages the test fails with:
>
> cannot populate ring_mp_mc mempool
> Test Failed
>
> Size the four mempools by the number of cores actually exercised.
>
> Return TEST_SKIPPED rather than -1 when allocation or populate of
> a mempool fails, so insufficient memory is reported as a skip and
> not as a test failure. Propagate the skip through the combined
> mempool_perf_autotest wrapper.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 4/7] app/test/mempool_perf: drop constant-values replay
2026-05-29 17:10 ` [PATCH 4/7] app/test/mempool_perf: drop constant-values replay Stephen Hemminger
@ 2026-06-01 8:34 ` Andrew Rybchenko
2026-06-01 13:22 ` Morten Brørup
0 siblings, 1 reply; 21+ messages in thread
From: Andrew Rybchenko @ 2026-06-01 8:34 UTC (permalink / raw)
To: Stephen Hemminger, dev; +Cc: Morten Brørup
On 5/29/26 8:10 PM, Stephen Hemminger wrote:
> The second nested matrix replays each (n_get_bulk == n_put_bulk)
> point with use_constant_values=1 to exercise the compile-time
> constant bulk-size paths in test_loop(). This roughly doubles the
> work for the get/put diagonal at every n_keep without adding new
> signal: the cycles/op result for a constant bulk is interesting in
> isolated inlining studies, not in routine regression sweeps.
>
> Drop the replay. The use_constant_values switch and its branches
> in test_loop() are retained for now since they are exercised by
> hand in any local benchmarking.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
As far as I can see you delete the only place where use_constant_values
is set to 1. It looks suspicious and basically preserves dead code.
Since Morten added the code, the patch should wait for his approval.
> ---
> app/test/test_mempool_perf.c | 8 --------
> 1 file changed, 8 deletions(-)
>
> diff --git a/app/test/test_mempool_perf.c b/app/test/test_mempool_perf.c
> index 19591ad0c9..dd2f0bbaca 100644
> --- a/app/test/test_mempool_perf.c
> +++ b/app/test/test_mempool_perf.c
> @@ -423,14 +423,6 @@ do_one_mempool_test(struct rte_mempool *mp, unsigned int cores, int external_cac
> ret = launch_cores(mp, cores);
> if (ret < 0)
> return -1;
> -
> - /* replay test with constant values */
> - if (n_get_bulk == n_put_bulk) {
> - use_constant_values = 1;
> - ret = launch_cores(mp, cores);
> - if (ret < 0)
> - return -1;
> - }
> }
> }
> }
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 5/7] app/test/mempool_perf: scale down for high core counts
2026-05-29 17:10 ` [PATCH 5/7] app/test/mempool_perf: scale down for high core counts Stephen Hemminger
@ 2026-06-01 8:42 ` Andrew Rybchenko
2026-06-01 12:58 ` Morten Brørup
1 sibling, 0 replies; 21+ messages in thread
From: Andrew Rybchenko @ 2026-06-01 8:42 UTC (permalink / raw)
To: Stephen Hemminger, dev; +Cc: Morten Brørup
On 5/29/26 8:10 PM, Stephen Hemminger wrote:
> On a 32-core system the test matrix runs the cartesian product of
> 4 mempools, 3 core-count configurations and ~340 (n_keep, bulk)
> points at TIME_S=1 second each: about 67 minutes total, well past
> the 10 minute perf-test timeout.
>
> Two reductions, no loss of meaningful signal:
>
> 1. Per-point duration: 1 second -> 200 ms. Each point currently
> collects 10^5-10^6 mempool ops; 200 ms still yields >10^4
> samples, well above the noise floor for a cycles-per-op average.
>
> 2. Matrix trim: drop adjacent bulk and n_keep points that don't
> produce regime changes. Retained set covers the boundaries
> that matter: 1, 4, cache-line burst (8), typical packet burst
> (32) and cache size (RTE_MEMPOOL_CACHE_MAX_SIZE = 512) for bulk;
> 32 (fits in cache), 512 (= cache size) and 32768 (far exceeds
> cache) for n_keep.
>
> Combined effect: ~10x runtime reduction.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
I have no strong opinion on the patch.
In general it LGTM and makes sense.
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> ---
> app/test/test_mempool_perf.c | 32 ++++++++++++--------------------
> 1 file changed, 12 insertions(+), 20 deletions(-)
>
> diff --git a/app/test/test_mempool_perf.c b/app/test/test_mempool_perf.c
> index dd2f0bbaca..6801812a8d 100644
> --- a/app/test/test_mempool_perf.c
> +++ b/app/test/test_mempool_perf.c
> @@ -61,26 +61,21 @@
> *
> * - Pseudorandom max bulk size (*n_max_bulk*)
> *
> - * - Max bulk from CACHE_LINE_BURST to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE,
> - * where CACHE_LINE_BURST is the number of pointers fitting into one CPU cache line.
> + * - Max bulk: CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE,
> + * where CACHE_LINE_BURST is the number of pointers fitting into
> + * one CPU cache line.
> *
> * - Fixed bulk size (*n_get_bulk*, *n_put_bulk*)
> *
> - * - Bulk get from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE
> - * - Bulk put from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE
> - * - Bulk get and put from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE, compile time constant
> + * - Bulk get: 1, 4, CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE
> + * - Bulk put: 1, 4, CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE
> *
> * - Number of kept objects (*n_keep*)
> *
> - * - 32
> - * - 128
> - * - 512
> - * - 2048
> - * - 8192
> - * - 32768
> + * - 32, 512, 32768
> */
>
> -#define TIME_S 1
> +#define TIME_MS 200
> #define MEMPOOL_ELT_SIZE 2048
> #define MAX_KEEP 32768
> #define N (128 * MAX_KEEP)
> @@ -257,7 +252,7 @@ per_lcore_mempool_test(void *arg)
>
> start_cycles = rte_get_timer_cycles();
>
> - while (time_diff/hz < TIME_S) {
> + while (time_diff < hz * TIME_MS / 1000) {
> if (n_max_bulk != 0)
> ret = test_loop_random(mp, cache, n_keep, n_max_bulk);
> else if (!use_constant_values)
> @@ -376,13 +371,10 @@ launch_cores(struct rte_mempool *mp, unsigned int cores)
> static int
> do_one_mempool_test(struct rte_mempool *mp, unsigned int cores, int external_cache)
> {
> - unsigned int bulk_tab_max[] = { CACHE_LINE_BURST, 32, 64, 128, 256,
> - RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
> - unsigned int bulk_tab_get[] = { 1, 4, CACHE_LINE_BURST, 32, 64, 128, 256,
> - RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
> - unsigned int bulk_tab_put[] = { 1, 4, CACHE_LINE_BURST, 32, 64, 128, 256,
> - RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
> - unsigned int keep_tab[] = { 32, 128, 512, 2048, 8192, 32768, 0 };
> + unsigned int bulk_tab_max[] = { CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
> + unsigned int bulk_tab_get[] = { 1, 4, CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
> + unsigned int bulk_tab_put[] = { 1, 4, CACHE_LINE_BURST, 32, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
> + unsigned int keep_tab[] = { 32, 512, 32768, 0 };
> unsigned int *max_bulk_ptr;
> unsigned int *get_bulk_ptr;
> unsigned int *put_bulk_ptr;
^ permalink raw reply [flat|nested] 21+ messages in thread
* RE: [PATCH 3/7] app/test/mempool_perf: size mempool by tested cores
2026-06-01 8:12 ` Andrew Rybchenko
@ 2026-06-01 12:22 ` Morten Brørup
0 siblings, 0 replies; 21+ messages in thread
From: Morten Brørup @ 2026-06-01 12:22 UTC (permalink / raw)
To: Andrew Rybchenko, Stephen Hemminger, dev
> From: Andrew Rybchenko [mailto:andrew.rybchenko@oktetlabs.ru]
> Sent: Monday, 1 June 2026 10.13
>
> On 5/29/26 8:10 PM, Stephen Hemminger wrote:
> > The mempool size is computed from rte_lcore_count() so on systems
> > with many lcores the test requires multiple GB of hugepages even
> > for the single-core and dual-core variants. On a 20 lcore system
> > with 2 GB of hugepages the test fails with:
> >
> > cannot populate ring_mp_mc mempool
> > Test Failed
> >
> > Size the four mempools by the number of cores actually exercised.
> >
> > Return TEST_SKIPPED rather than -1 when allocation or populate of
> > a mempool fails, so insufficient memory is reported as a skip and
> > not as a test failure. Propagate the skip through the combined
> > mempool_perf_autotest wrapper.
> >
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
LGTM too.
Acked-by: Morten Brørup <mb@smartsharesystems.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* RE: [PATCH 5/7] app/test/mempool_perf: scale down for high core counts
2026-05-29 17:10 ` [PATCH 5/7] app/test/mempool_perf: scale down for high core counts Stephen Hemminger
2026-06-01 8:42 ` Andrew Rybchenko
@ 2026-06-01 12:58 ` Morten Brørup
1 sibling, 0 replies; 21+ messages in thread
From: Morten Brørup @ 2026-06-01 12:58 UTC (permalink / raw)
To: Stephen Hemminger, Andrew Rybchenko, dev
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Friday, 29 May 2026 19.11
>
> On a 32-core system the test matrix runs the cartesian product of
> 4 mempools, 3 core-count configurations and ~340 (n_keep, bulk)
> points at TIME_S=1 second each: about 67 minutes total, well past
> the 10 minute perf-test timeout.
>
> Two reductions, no loss of meaningful signal:
>
> 1. Per-point duration: 1 second -> 200 ms. Each point currently
> collects 10^5-10^6 mempool ops; 200 ms still yields >10^4
> samples, well above the noise floor for a cycles-per-op average.
Ack to this.
>
> 2. Matrix trim: drop adjacent bulk and n_keep points that don't
> produce regime changes. Retained set covers the boundaries
> that matter: 1, 4, cache-line burst (8), typical packet burst
> (32) and cache size (RTE_MEMPOOL_CACHE_MAX_SIZE = 512) for bulk;
> 32 (fits in cache), 512 (= cache size) and 32768 (far exceeds
> cache) for n_keep.
My mempool optimization patch [1] introduces a bounce buffer limit, so huge requests are not needlessly copied twice to bounce through the cache, but are moved directly between application memory and the mempool backend driver.
The bounce buffer limit is half the cache size.
So, please keep 256. Maybe change it to RTE_MEMPOOL_CACHE_MAX_SIZE / 2.
[1]: https://patchwork.dpdk.org/project/dpdk/patch/20260526140000.175092-1-mb@smartsharesystems.com/
Also consider keeping 64; it seems to be a popular default burst size for some CPUs.
On the other hand, if the patch introducing default mbuf burst sizes [2] gets accepted, we could replace 32 with RTE_MBUF_BURST_SIZE_THROUGHPUT and 4 with RTE_MBUF_BURST_SIZE_LATENCY.
No strong opinion on 64; I'll leave that up to you.
[2]: https://patchwork.dpdk.org/project/dpdk/list/?series=37914
>
> Combined effect: ~10x runtime reduction.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
With suggested changes,
Acked-by: Morten Brørup <mb@smartsharesystems.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* RE: [PATCH 4/7] app/test/mempool_perf: drop constant-values replay
2026-06-01 8:34 ` Andrew Rybchenko
@ 2026-06-01 13:22 ` Morten Brørup
0 siblings, 0 replies; 21+ messages in thread
From: Morten Brørup @ 2026-06-01 13:22 UTC (permalink / raw)
To: Andrew Rybchenko, Stephen Hemminger, dev
> From: Andrew Rybchenko [mailto:andrew.rybchenko@oktetlabs.ru]
> Sent: Monday, 1 June 2026 10.35
>
> On 5/29/26 8:10 PM, Stephen Hemminger wrote:
> > The second nested matrix replays each (n_get_bulk == n_put_bulk)
> > point with use_constant_values=1 to exercise the compile-time
> > constant bulk-size paths in test_loop(). This roughly doubles the
> > work for the get/put diagonal at every n_keep without adding new
> > signal: the cycles/op result for a constant bulk is interesting in
> > isolated inlining studies, not in routine regression sweeps.
> >
> > Drop the replay. The use_constant_values switch and its branches
> > in test_loop() are retained for now since they are exercised by
> > hand in any local benchmarking.
> >
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>
> As far as I can see you delete the only place where use_constant_values
> is set to 1. It looks suspicious and basically preserves dead code.
> Since Morten added the code, the patch should wait for his approval.
Having used the mempool perf test extensively myself, I agree that it is painfully slow.
Mempools are very often used with constant request sizes, so testing their performance remains relevant for regression sweeps too.
NAK to this change.
Maybe the testing of constant values could be reduced by using a subset of the non-constant mix of values.
>
> > ---
> > app/test/test_mempool_perf.c | 8 --------
> > 1 file changed, 8 deletions(-)
> >
> > diff --git a/app/test/test_mempool_perf.c
> b/app/test/test_mempool_perf.c
> > index 19591ad0c9..dd2f0bbaca 100644
> > --- a/app/test/test_mempool_perf.c
> > +++ b/app/test/test_mempool_perf.c
> > @@ -423,14 +423,6 @@ do_one_mempool_test(struct rte_mempool *mp,
> unsigned int cores, int external_cac
> > ret = launch_cores(mp, cores);
> > if (ret < 0)
> > return -1;
> > -
> > - /* replay test with constant values */
> > - if (n_get_bulk == n_put_bulk) {
> > - use_constant_values = 1;
> > - ret = launch_cores(mp, cores);
> > - if (ret < 0)
> > - return -1;
> > - }
> > }
> > }
> > }
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
` (6 preceding siblings ...)
2026-05-29 17:11 ` [PATCH 7/7] app/test/test_pmd_perf: skip if no device available Stephen Hemminger
@ 2026-08-26 1:56 ` Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 1/5] app/test/reciprocal_division: make it a fast test Stephen Hemminger
` (4 more replies)
7 siblings, 5 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-08-26 1:56 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
Several of the perf/autotests assume server-class machines: they run for
billions of iterations, or size hugepage allocations by total lcore count,
which makes them time out or fail to allocate on smaller systems and on
machines with high core counts but modest memory.
This series trims runtime and memory use without losing meaningful test
coverage, and reports resource shortfalls as skips rather than failures.
The goal is a perf suite that can be run regularly to catch large
regressions, so finishing reliably matters more than fine resolution.
Measured with "meson test --suite=perf-tests" on a 32 lcore system with
10 GB of hugepages, same machine and same session before and after:
main this series
Ok 41 44
Fail 1 0
Timeout 4 0
mempool_perf_autotest timeout 414s
mempool_perf_autotest_1core timeout 83s
mempool_perf_autotest_2cores timeout 84s
mempool_perf_autotest_allcores timeout 200s
rcu_qsbr_perf_autotest 495s 32s
reciprocal_division_perf 252s 1s
reciprocal_division 104s moved to fast-tests
pmd_perf_autotest FAIL skip
total suite 65.5 min 24.8 min
The 65.5 minutes understates it: four of those tests were killed at the
600 second timeout rather than finishing, so the real figure is unknown
and larger.
Note that with enough memory for the largest mempool, all four mempool
variants time out on main, including the single core one. Memory is not
the only problem; the test also has no working bound on its own runtime.
Two distinct problems were behind that, and both needed fixing:
- test_loop() did a fixed number of objects per call, and the elapsed
time is only checked between calls. A small bulk size needs many more
mempool operations for the same objects, and each operation is much
more expensive when many cores contend, so with bulk size 1 on 32
cores a single call took over 50 seconds and TIME_MS could not bound
anything. The work per call is now limited by mempool operations.
- Each test point launches and joins every lcore. That costs about 2 ms
on one core but over a second on 32, so the runtime is set by the
number of points rather than by the time spent measuring. Above two
cores a reduced set of get/put bulk sizes is used.
On a machine with less memory the mempool sizing matters too: sizing the
pools by the cores actually exercised lets the one and two core variants
run where they previously could not allocate at all, and a shortfall is
now reported as a skip rather than a failure.
v2 changes:
- Patch 5 no longer drops the constant-values replay. Morten pointed
out that mempools are commonly used with compile time constant request
sizes, so those paths are real regression signal, and NAKed the
removal. The replay is kept but restricted to a subset of the bulk
sizes rather than the whole get/put diagonal.
- The bulk size tables keep 64 and RTE_MEMPOOL_CACHE_MAX_SIZE / 2. The
latter is the bounce buffer limit in Morten's mempool optimization
work, above which requests bypass the cache, so it marks a real
change in behaviour.
- The mempool patches are squashed into one per test file. The result
contains considerably more than was reviewed in v1, so the acks given
on the v1 mempool patches have been dropped rather than carried
forward.
- Added the test_loop() bound and the reduced bulk table described
above, plus per-point elapsed time and a flush before measuring, so a
run killed by a timeout shows where it got to. That is how the
50 second points were found.
Stephen Hemminger (5):
app/test/reciprocal_division: make it a fast test
app/test/reciprocal_division_perf: reduce test time
app/test/test_rcu_qsbr_perf: call quiescent more often
app/test/test_pmd_perf: skip if no device available
app/test/mempool_perf: adjust test for large core counts
app/test/test_mempool_perf.c | 179 ++++++++++-----
app/test/test_pmd_perf.c | 2 +-
app/test/test_rcu_qsbr_perf.c | 3 +-
app/test/test_reciprocal_division.c | 279 +++++++++++++----------
app/test/test_reciprocal_division_perf.c | 4 +-
5 files changed, 281 insertions(+), 186 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 1/5] app/test/reciprocal_division: make it a fast test
2026-08-26 1:56 ` [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems Stephen Hemminger
@ 2026-08-26 1:56 ` Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 2/5] app/test/reciprocal_division_perf: reduce test time Stephen Hemminger
` (3 subsequent siblings)
4 siblings, 0 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-08-26 1:56 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
This test is useful to have in CI, but the iteration values
were too large to make it usable as a fast test.
Redo the test with checks around boundary values and
use unit test framework for sub tests.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_reciprocal_division.c | 279 ++++++++++++++++------------
1 file changed, 157 insertions(+), 122 deletions(-)
diff --git a/app/test/test_reciprocal_division.c b/app/test/test_reciprocal_division.c
index 3d0736d8dd..80f8561523 100644
--- a/app/test/test_reciprocal_division.c
+++ b/app/test/test_reciprocal_division.c
@@ -5,162 +5,197 @@
#include "test.h"
#include <stdio.h>
-#include <unistd.h>
#include <inttypes.h>
#include <rte_common.h>
-#include <rte_cycles.h>
#include <rte_random.h>
#include <rte_reciprocal.h>
-#define MAX_ITERATIONS (1ULL << 32)
-#define DIVIDE_ITER (100)
+#define MAX_ITERATIONS (1ULL << 20)
+#define DIVISORS_RANDOM 64
static int
-test_reciprocal(void)
+test_u32_divide(uint32_t a, uint32_t d, struct rte_reciprocal r)
{
- int result = 0;
- uint32_t divisor_u32 = 0;
- uint32_t dividend_u32;
- uint32_t nresult_u32;
- uint32_t rresult_u32;
- uint64_t i, j;
- uint64_t divisor_u64 = 0;
- uint64_t dividend_u64;
- uint64_t nresult_u64;
- uint64_t rresult_u64;
- struct rte_reciprocal reci_u32 = {0};
- struct rte_reciprocal_u64 reci_u64 = {0};
-
- printf("Validating unsigned 32bit division.\n");
- for (i = 0; i < MAX_ITERATIONS; i++) {
- /* Change divisor every DIVIDE_ITER iterations. */
- if (i % DIVIDE_ITER == 0) {
- divisor_u32 = rte_rand();
- reci_u32 = rte_reciprocal_value(divisor_u32);
- }
-
- dividend_u32 = rte_rand();
- nresult_u32 = dividend_u32 / divisor_u32;
- rresult_u32 = rte_reciprocal_divide(dividend_u32,
- reci_u32);
- if (nresult_u32 != rresult_u32) {
- printf("Division failed, %"PRIu32"/%"PRIu32" = "
- "expected %"PRIu32" result %"PRIu32"\n",
- dividend_u32, divisor_u32,
- nresult_u32, rresult_u32);
- result = 1;
- break;
- }
- }
+ uint32_t expected = a / d;
+ uint32_t result = rte_reciprocal_divide(a, r);
- printf("Validating unsigned 64bit division.\n");
- for (i = 0; i < MAX_ITERATIONS; i++) {
- /* Change divisor every DIVIDE_ITER iterations. */
- if (i % DIVIDE_ITER == 0) {
- divisor_u64 = rte_rand();
- reci_u64 = rte_reciprocal_value_u64(divisor_u64);
- }
+ TEST_ASSERT_EQUAL(expected, result,
+ "%"PRIu32"/%"PRIu32" expected %"PRIu32" got %"PRIu32,
+ a, d, expected, result);
+ return 0;
+}
- dividend_u64 = rte_rand();
- nresult_u64 = dividend_u64 / divisor_u64;
- rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
- &reci_u64);
- if (nresult_u64 != rresult_u64) {
- printf("Division failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- break;
+static int
+test_reciprocal_u32(void)
+{
+ const uint32_t edge_div_u32[] = {
+ 1, 2, 3, 7, 0x7fffffff, 0x80000000, 0xfffffffe, UINT32_MAX,
+ };
+ unsigned int n_div = RTE_DIM(edge_div_u32) + DIVISORS_RANDOM;
+
+ for (unsigned int di = 0; di < n_div; di++) {
+ uint32_t d;
+ if (di < RTE_DIM(edge_div_u32))
+ d = edge_div_u32[di]; /* Make sure and test the edge cases */
+ else
+ d = rte_rand_max(UINT32_MAX - 1) + 1;
+
+ struct rte_reciprocal r = rte_reciprocal_value(d);
+ uint32_t qmax = UINT32_MAX / d; /* largest q with q*d <= UINT32_MAX */
+ if (d != 1)
+ qmax++;
+
+ for (unsigned int k = 0; k < MAX_ITERATIONS; k++) {
+ uint32_t q = rte_rand_max(qmax);
+ uint32_t val = q * d; /* fits in u32 */
+
+ /* Check around the value.
+ * Under and overflow of 32 bit value are fine here.
+ */
+ if (test_u32_divide(val - 1, d, r) < 0 ||
+ test_u32_divide(val, d, r) < 0 ||
+ test_u32_divide(val + 1, d, r) < 0)
+ return -1;
}
}
+ return TEST_SUCCESS;
+}
- printf("Validating unsigned 64bit division with 32bit divisor.\n");
- for (i = 0; i < MAX_ITERATIONS; i++) {
- /* Change divisor every DIVIDE_ITER iterations. */
- if (i % DIVIDE_ITER == 0) {
- divisor_u64 = rte_rand() >> 32;
- reci_u64 = rte_reciprocal_value_u64(divisor_u64);
- }
+static int
+test_u64_divide(uint64_t a, uint64_t d, const struct rte_reciprocal_u64 *r)
+{
+ uint64_t expected = a / d;
+ uint64_t result = rte_reciprocal_divide_u64(a, r);
+
+ TEST_ASSERT_EQUAL(expected, result,
+ "%"PRIu64"/%"PRIu64" expected %"PRIu64" got %"PRIu64,
+ a, d, expected, result);
+ return 0;
+}
- dividend_u64 = rte_rand();
- nresult_u64 = dividend_u64 / divisor_u64;
- rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
- &reci_u64);
+static int
+test_reciprocal_u64(void)
+{
+ const uint64_t edge_div_u64[] = {
+ 1, 2, 3, 7, 0x7fffffff, 0x80000000, 0xfffffffe, UINT64_MAX,
+ };
+ unsigned int n_div = RTE_DIM(edge_div_u64) + DIVISORS_RANDOM;
+
+ for (unsigned int di = 0; di < n_div; di++) {
+ uint64_t d;
+ if (di < RTE_DIM(edge_div_u64))
+ d = edge_div_u64[di];
+ else
+ d = rte_rand_max(UINT64_MAX - 1) + 1;
+
+ struct rte_reciprocal_u64 r = rte_reciprocal_value_u64(d);
+ uint64_t qmax = UINT64_MAX / d; /* largest q with q*d <= UINT64_MAX */
+ if (d != 1)
+ ++qmax;
+
+ for (unsigned int k = 0; k < MAX_ITERATIONS; k++) {
+ uint64_t q = rte_rand_max(qmax);
+ uint64_t val = q * d;
+
+ if (test_u64_divide(val - 1, d, &r) < 0 ||
+ test_u64_divide(val, d, &r) < 0 ||
+ test_u64_divide(val + 1, d, &r) < 0)
+ return -1;
- if (nresult_u64 != rresult_u64) {
- printf("Division failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- break;
}
}
+ return TEST_SUCCESS;
+}
- printf("Validating division by power of 2.\n");
- for (i = 0; i < 32; i++) {
- divisor_u64 = 1ull << i;
- reci_u64 = rte_reciprocal_value_u64(divisor_u64);
- reci_u32 = rte_reciprocal_value((uint32_t)divisor_u64);
+static int
+test_reciprocal_u64_small(void)
+{
+ /* 64-bit division with a 32-bit-range divisor */
+ uint64_t divisor_u64 = (rte_rand() >> 32) | 1;
+ struct rte_reciprocal_u64 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+
+ for (unsigned int i = 0; i < MAX_ITERATIONS; i++) {
+ uint64_t dividend_u64 = rte_rand();
+ uint64_t nresult_u64 = dividend_u64 / divisor_u64;
+ uint64_t rresult_u64 = rte_reciprocal_divide_u64(dividend_u64, &reci_u64);
+
+ TEST_ASSERT_EQUAL(nresult_u64, rresult_u64,
+ "%"PRIu64"/%"PRIu64" = expected %"PRIu64" got %"PRIu64,
+ dividend_u64, divisor_u64, nresult_u64, rresult_u64);
+ }
- for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
- dividend_u64 = rte_rand();
+ return TEST_SUCCESS;
+}
- nresult_u64 = dividend_u64 / divisor_u64;
- rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+static int
+test_reciprocal_pow2(void)
+{
+ for (unsigned int i = 0; i < 32; i++) {
+ uint64_t divisor_u64 = 1ULL << i;
+ struct rte_reciprocal_u64 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ struct rte_reciprocal reci_u32 = rte_reciprocal_value((uint32_t)divisor_u64);
+
+ for (unsigned int j = 0; j < MAX_ITERATIONS >> 4; j++) {
+ uint64_t dividend_u64 = rte_rand();
+ uint64_t nresult_u64 = dividend_u64 / divisor_u64;
+ uint64_t rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
&reci_u64);
- if (nresult_u64 != rresult_u64) {
- printf(
- "Division 64 failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- }
-
- nresult_u32 = (dividend_u64 >> 32) / divisor_u64;
- rresult_u32 = rte_reciprocal_divide(
+ TEST_ASSERT_EQUAL(nresult_u64, rresult_u64,
+ "u64 %"PRIu64"/%"PRIu64" = expected %"PRIu64" got %"PRIu64,
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
+
+ uint32_t nresult_u32 = (dividend_u64 >> 32) / divisor_u64;
+ uint32_t rresult_u32 = rte_reciprocal_divide(
(dividend_u64 >> 32), reci_u32);
- if (nresult_u32 != rresult_u32) {
- printf(
- "Division 32 failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64 >> 32, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- break;
- }
+ TEST_ASSERT_EQUAL(nresult_u32, rresult_u32,
+ "u32 %"PRIu64"/%"PRIu64" = expected %"PRIu32" got %"PRIu32,
+ dividend_u64 >> 32, divisor_u64,
+ nresult_u32, rresult_u32);
}
}
- for (; i < 64; i++) {
- divisor_u64 = 1ull << i;
- reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ for (unsigned int i = 32; i < 64; i++) {
+ uint64_t divisor_u64 = 1ULL << i;
+ struct rte_reciprocal_u64 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
- for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
- dividend_u64 = rte_rand();
-
- nresult_u64 = dividend_u64 / divisor_u64;
- rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ for (unsigned int j = 0; j < MAX_ITERATIONS >> 4; j++) {
+ uint64_t dividend_u64 = rte_rand();
+ uint64_t nresult_u64 = dividend_u64 / divisor_u64;
+ uint64_t rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
&reci_u64);
- if (nresult_u64 != rresult_u64) {
- printf("Division failed, %"PRIu64"/%"PRIu64" = "
- "expected %"PRIu64" result %"PRIu64"\n",
- dividend_u64, divisor_u64,
- nresult_u64, rresult_u64);
- result = 1;
- break;
- }
+ TEST_ASSERT_EQUAL(nresult_u64, rresult_u64,
+ "u64 %"PRIu64"/%"PRIu64" = expected %"PRIu64" got %"PRIu64,
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
}
}
- return result;
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite reciprocal_tests = {
+ .suite_name = "reciprocal division autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_reciprocal_u32),
+ TEST_CASE(test_reciprocal_u64),
+ TEST_CASE(test_reciprocal_u64_small),
+ TEST_CASE(test_reciprocal_pow2),
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_reciprocal(void)
+{
+ return unit_test_suite_runner(&reciprocal_tests);
}
-REGISTER_PERF_TEST(reciprocal_division, test_reciprocal);
+REGISTER_FAST_TEST(reciprocal_division_autotest, NOHUGE_OK, ASAN_OK, test_reciprocal);
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 2/5] app/test/reciprocal_division_perf: reduce test time
2026-08-26 1:56 ` [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 1/5] app/test/reciprocal_division: make it a fast test Stephen Hemminger
@ 2026-08-26 1:56 ` Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 3/5] app/test/test_rcu_qsbr_perf: call quiescent more often Stephen Hemminger
` (2 subsequent siblings)
4 siblings, 0 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-08-26 1:56 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
The test time was excessively long it does not need to go
for 2^32 iterations.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_reciprocal_division_perf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/test/test_reciprocal_division_perf.c b/app/test/test_reciprocal_division_perf.c
index 6c8afc6e36..046a77f5f2 100644
--- a/app/test/test_reciprocal_division_perf.c
+++ b/app/test/test_reciprocal_division_perf.c
@@ -13,8 +13,8 @@
#include <rte_random.h>
#include <rte_reciprocal.h>
-#define MAX_ITERATIONS (1ULL << 32)
-#define DIVIDE_ITER (1ULL << 28)
+#define MAX_ITERATIONS (1ULL << 24)
+#define DIVIDE_ITER (1ULL << 10)
static int
test_reciprocal_division_perf(void)
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 3/5] app/test/test_rcu_qsbr_perf: call quiescent more often
2026-08-26 1:56 ` [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 1/5] app/test/reciprocal_division: make it a fast test Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 2/5] app/test/reciprocal_division_perf: reduce test time Stephen Hemminger
@ 2026-08-26 1:56 ` Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 4/5] app/test/test_pmd_perf: skip if no device available Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 5/5] app/test/mempool_perf: adjust test to work with many cores Stephen Hemminger
4 siblings, 0 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-08-26 1:56 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
The performance test would generate large backlog of quiescent
actions which caused test to take excessively long time.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_rcu_qsbr_perf.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/app/test/test_rcu_qsbr_perf.c b/app/test/test_rcu_qsbr_perf.c
index bdffd64e60..8768a9ce1a 100644
--- a/app/test/test_rcu_qsbr_perf.c
+++ b/app/test/test_rcu_qsbr_perf.c
@@ -313,9 +313,8 @@ test_rcu_qsbr_hash_reader(void *arg)
pdata[thread_id]++;
}
rte_rcu_qsbr_unlock(temp, thread_id);
+ rte_rcu_qsbr_quiescent(temp, thread_id);
}
- /* Update quiescent state counter */
- rte_rcu_qsbr_quiescent(temp, thread_id);
rte_rcu_qsbr_thread_offline(temp, thread_id);
loop_cnt++;
} while (!writer_done);
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 4/5] app/test/test_pmd_perf: skip if no device available
2026-08-26 1:56 ` [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems Stephen Hemminger
` (2 preceding siblings ...)
2026-08-26 1:56 ` [PATCH v2 3/5] app/test/test_rcu_qsbr_perf: call quiescent more often Stephen Hemminger
@ 2026-08-26 1:56 ` Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 5/5] app/test/mempool_perf: adjust test to work with many cores Stephen Hemminger
4 siblings, 0 replies; 21+ messages in thread
From: Stephen Hemminger @ 2026-08-26 1:56 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
Rather than exiting with FAILURE the test should exit
with SKIPPED status if it can't find a device to attach to.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_pmd_perf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/test/test_pmd_perf.c b/app/test/test_pmd_perf.c
index 995b0a6f20..8eff0a1223 100644
--- a/app/test/test_pmd_perf.c
+++ b/app/test/test_pmd_perf.c
@@ -691,7 +691,7 @@ test_pmd_perf(void)
if (nb_ports < NB_ETHPORTS_USED) {
printf("At least %u port(s) used for perf. test\n",
NB_ETHPORTS_USED);
- return -1;
+ return TEST_SKIPPED;
}
nb_lcores = rte_lcore_count();
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 5/5] app/test/mempool_perf: adjust test to work with many cores
2026-08-26 1:56 ` [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems Stephen Hemminger
` (3 preceding siblings ...)
2026-08-26 1:56 ` [PATCH v2 4/5] app/test/test_pmd_perf: skip if no device available Stephen Hemminger
@ 2026-08-26 1:56 ` Stephen Hemminger
2026-08-26 3:58 ` Morten Brørup
4 siblings, 1 reply; 21+ messages in thread
From: Stephen Hemminger @ 2026-08-26 1:56 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
On a system with many lcores this test both fails to allocate on a
machine with modest memory and runs far past the 10 minute perf-test
timeout. With enough hugepages for the largest mempool, all four
variants time out, including the single core one.
Size the four mempools by the number of cores actually exercised
rather than by rte_lcore_count(), and report a shortfall as
TEST_SKIPPED rather than a failure. Run the largest core count
first in the combined test, so a machine which cannot fit it skips
immediately instead of spending minutes on the smaller runs.
Reduce the time per test point from 1 second to 200 ms and drop the
n_keep values which do not mark a change in behaviour, keeping 32,
512 and 32768. For bulk sizes keep 1, 4, CACHE_LINE_BURST, 32, 64,
RTE_MEMPOOL_CACHE_MAX_SIZE / 2 and RTE_MEMPOOL_CACHE_MAX_SIZE; the
second to last is the bounce buffer limit above which requests
bypass the cache. Replay a subset of those with compile time
constant values rather than the whole get/put diagonal, since
mempools are commonly used with constant request sizes and those
paths still need covering.
The elapsed time is only checked between calls to test_loop(), and
one call did a fixed number of objects. A small bulk size needs
many more mempool operations for those objects, and each operation
is much more expensive when many cores contend for the ring, so with
bulk size 1 on 32 cores a single call took over 50 seconds and
TIME_MS could not bound anything:
n_keep=32768 n_get_bulk=1 n_put_bulk=1 elapsed_ms=53431
Limit the mempool operations per call instead of the objects, and
return the number of objects handled so the reported rate stays
correct.
Each test point also launches and joins every lcore, which costs
about 2 ms on one core but over a second on 32, so use a reduced set
of get/put bulk sizes above two cores.
Print the elapsed time of each point and flush before measuring, so
a run killed by a timeout shows where it got to.
On a 32 lcore system with 10 GB of hugepages:
mempool_perf_autotest timeout -> 414s
mempool_perf_autotest_1core timeout -> 83s
mempool_perf_autotest_2cores timeout -> 84s
mempool_perf_autotest_allcores timeout -> 200s
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_mempool_perf.c | 179 +++++++++++++++++++++++------------
1 file changed, 120 insertions(+), 59 deletions(-)
diff --git a/app/test/test_mempool_perf.c b/app/test/test_mempool_perf.c
index e164eca788..8313bdc1fc 100644
--- a/app/test/test_mempool_perf.c
+++ b/app/test/test_mempool_perf.c
@@ -43,7 +43,7 @@
* Each core get *n_keep* objects per bulk of *n_get_bulk*. Then,
* objects are put back in the pool per bulk of *n_put_bulk*.
*
- * This sequence is done during TIME_S seconds.
+ * This sequence is done during TIME_MS milliseconds.
*
* This test is done on the following configurations:
*
@@ -61,30 +61,32 @@
*
* - Pseudorandom max bulk size (*n_max_bulk*)
*
- * - Max bulk from CACHE_LINE_BURST to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE,
- * where CACHE_LINE_BURST is the number of pointers fitting into one CPU cache line.
+ * - Max bulk: CACHE_LINE_BURST, 32, 64, RTE_MEMPOOL_CACHE_MAX_SIZE / 2
+ * and RTE_MEMPOOL_CACHE_MAX_SIZE, where CACHE_LINE_BURST is the
+ * number of pointers fitting into one CPU cache line.
*
* - Fixed bulk size (*n_get_bulk*, *n_put_bulk*)
*
- * - Bulk get from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE
- * - Bulk put from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE
- * - Bulk get and put from 1 to 256, and RTE_MEMPOOL_CACHE_MAX_SIZE, compile time constant
+ * - Bulk get: 1, 4, CACHE_LINE_BURST, 32, 64,
+ * RTE_MEMPOOL_CACHE_MAX_SIZE / 2, RTE_MEMPOOL_CACHE_MAX_SIZE
+ * - Bulk put: 1, 4, CACHE_LINE_BURST, 32, 64,
+ * RTE_MEMPOOL_CACHE_MAX_SIZE / 2, RTE_MEMPOOL_CACHE_MAX_SIZE
+ * - Bulk get and put of 1, CACHE_LINE_BURST, 32 and
+ * RTE_MEMPOOL_CACHE_MAX_SIZE, compile time constant
*
* - Number of kept objects (*n_keep*)
*
- * - 32
- * - 128
- * - 512
- * - 2048
- * - 8192
- * - 32768
+ * - 32, 512, 32768
*/
-#define TIME_S 1
+#define TIME_MS 200
+/* above this many cores, use the reduced bulk size tables */
+#define MANYCORE_THRESHOLD 2
#define MEMPOOL_ELT_SIZE 2048
#define MAX_KEEP 32768
#define N (128 * MAX_KEEP)
-#define MEMPOOL_SIZE ((rte_lcore_count()*(MAX_KEEP+RTE_MEMPOOL_CACHE_MAX_SIZE*2))-1)
+/* max mempool operations per call to test_loop() */
+#define MAX_OPS (256 * 1024)
/* Number of pointers fitting into one cache line. */
#define CACHE_LINE_BURST (RTE_CACHE_LINE_SIZE / sizeof(uintptr_t))
@@ -147,9 +149,21 @@ test_loop(struct rte_mempool *mp, struct rte_mempool_cache *cache,
alignas(RTE_CACHE_LINE_SIZE) void *obj_table[MAX_KEEP];
unsigned int idx;
unsigned int i;
+ unsigned int iter;
int ret;
- for (i = 0; likely(i < (N / x_keep)); i++) {
+ /*
+ * The elapsed time is only checked between calls to this function,
+ * so bound the work done by one call. A small bulk size means many
+ * more mempool operations for the same number of objects, and each
+ * operation is far more expensive when many cores contend, so limit
+ * the operations rather than the objects.
+ */
+ iter = MAX_OPS / (x_keep / x_get_bulk + x_keep / x_put_bulk);
+ if (iter == 0)
+ iter = 1;
+
+ for (i = 0; likely(i < iter); i++) {
/* get x_keep objects by bulk of x_get_bulk */
for (idx = 0; idx < x_keep; idx += x_get_bulk) {
ret = rte_mempool_generic_get(mp,
@@ -171,7 +185,7 @@ test_loop(struct rte_mempool *mp, struct rte_mempool_cache *cache,
}
}
- return 0;
+ return iter * x_keep;
}
static __rte_always_inline int
@@ -215,7 +229,7 @@ test_loop_random(struct rte_mempool *mp, struct rte_mempool_cache *cache,
}
}
- return 0;
+ return N;
}
static int
@@ -258,7 +272,7 @@ per_lcore_mempool_test(void *arg)
start_cycles = rte_get_timer_cycles();
- while (time_diff/hz < TIME_S) {
+ while (time_diff < hz * TIME_MS / 1000) {
if (n_max_bulk != 0)
ret = test_loop_random(mp, cache, n_keep, n_max_bulk);
else if (!use_constant_values)
@@ -289,7 +303,7 @@ per_lcore_mempool_test(void *arg)
end_cycles = rte_get_timer_cycles();
time_diff = end_cycles - start_cycles;
- stats[lcore_id].enq_count += N;
+ stats[lcore_id].enq_count += ret;
}
stats[lcore_id].duration_cycles = time_diff;
@@ -312,6 +326,7 @@ launch_cores(struct rte_mempool *mp, unsigned int cores)
int ret;
unsigned int cores_save = cores;
double hz = rte_get_timer_hz();
+ uint64_t start = rte_get_timer_cycles();
rte_atomic_store_explicit(&synchro, 0, rte_memory_order_relaxed);
@@ -330,7 +345,10 @@ launch_cores(struct rte_mempool *mp, unsigned int cores)
n_get_bulk, n_put_bulk,
use_constant_values);
- if (rte_mempool_avail_count(mp) != MEMPOOL_SIZE) {
+ /* show progress if test is killed by timeout */
+ fflush(stdout);
+
+ if (rte_mempool_avail_count(mp) != mp->size) {
printf("mempool is not full\n");
return -1;
}
@@ -368,7 +386,8 @@ launch_cores(struct rte_mempool *mp, unsigned int cores)
rate += (double)stats[lcore_id].enq_count * hz /
(double)stats[lcore_id].duration_cycles;
- printf("rate_persec=%10" PRIu64 "\n", rate);
+ printf("rate_persec=%10" PRIu64 " elapsed_ms=%4.0f\n", rate,
+ (rte_get_timer_cycles() - start) * 1000.0 / hz);
return 0;
}
@@ -377,19 +396,34 @@ launch_cores(struct rte_mempool *mp, unsigned int cores)
static int
do_one_mempool_test(struct rte_mempool *mp, unsigned int cores, int external_cache)
{
- unsigned int bulk_tab_max[] = { CACHE_LINE_BURST, 32, 64, 128, 256,
- RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
- unsigned int bulk_tab_get[] = { 1, 4, CACHE_LINE_BURST, 32, 64, 128, 256,
+ unsigned int bulk_tab_max[] = { CACHE_LINE_BURST, 32, 64,
+ RTE_MEMPOOL_CACHE_MAX_SIZE / 2, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
+ unsigned int bulk_tab_get[] = { 1, 4, CACHE_LINE_BURST, 32, 64,
+ RTE_MEMPOOL_CACHE_MAX_SIZE / 2, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
+ unsigned int bulk_tab_put[] = { 1, 4, CACHE_LINE_BURST, 32, 64,
+ RTE_MEMPOOL_CACHE_MAX_SIZE / 2, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
+ /* launch overhead dominates with many cores, so test fewer sizes */
+ unsigned int bulk_tab_get_manycore[] = { 1, 32,
+ RTE_MEMPOOL_CACHE_MAX_SIZE / 2, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
+ unsigned int bulk_tab_put_manycore[] = { 1, 32,
+ RTE_MEMPOOL_CACHE_MAX_SIZE / 2, RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
+ /* subset of the get/put bulk sizes, replayed with constant values */
+ unsigned int bulk_tab_const[] = { 1, CACHE_LINE_BURST, 32,
RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
- unsigned int bulk_tab_put[] = { 1, 4, CACHE_LINE_BURST, 32, 64, 128, 256,
- RTE_MEMPOOL_CACHE_MAX_SIZE, 0 };
- unsigned int keep_tab[] = { 32, 128, 512, 2048, 8192, 32768, 0 };
+ unsigned int keep_tab[] = { 32, 512, 32768, 0 };
unsigned int *max_bulk_ptr;
unsigned int *get_bulk_ptr;
unsigned int *put_bulk_ptr;
unsigned int *keep_ptr;
+ unsigned int *get_tab = bulk_tab_get;
+ unsigned int *put_tab = bulk_tab_put;
int ret;
+ if (cores > MANYCORE_THRESHOLD) {
+ get_tab = bulk_tab_get_manycore;
+ put_tab = bulk_tab_put_manycore;
+ }
+
for (keep_ptr = keep_tab; *keep_ptr; keep_ptr++) {
for (max_bulk_ptr = bulk_tab_max; *max_bulk_ptr; max_bulk_ptr++) {
@@ -409,8 +443,8 @@ do_one_mempool_test(struct rte_mempool *mp, unsigned int cores, int external_cac
}
for (keep_ptr = keep_tab; *keep_ptr; keep_ptr++) {
- for (get_bulk_ptr = bulk_tab_get; *get_bulk_ptr; get_bulk_ptr++) {
- for (put_bulk_ptr = bulk_tab_put; *put_bulk_ptr; put_bulk_ptr++) {
+ for (get_bulk_ptr = get_tab; *get_bulk_ptr; get_bulk_ptr++) {
+ for (put_bulk_ptr = put_tab; *put_bulk_ptr; put_bulk_ptr++) {
if (*keep_ptr < *get_bulk_ptr || *keep_ptr < *put_bulk_ptr)
continue;
@@ -424,18 +458,34 @@ do_one_mempool_test(struct rte_mempool *mp, unsigned int cores, int external_cac
ret = launch_cores(mp, cores);
if (ret < 0)
return -1;
-
- /* replay test with constant values */
- if (n_get_bulk == n_put_bulk) {
- use_constant_values = 1;
- ret = launch_cores(mp, cores);
- if (ret < 0)
- return -1;
- }
}
}
}
+ /*
+ * Replay a subset of the bulk sizes with compile time constant
+ * values, to cover the inlined constant bulk paths. Only the
+ * n_get_bulk == n_put_bulk diagonal is valid here, and a subset
+ * of it is enough to catch a regression in those paths.
+ */
+ for (keep_ptr = keep_tab; *keep_ptr; keep_ptr++) {
+ for (get_bulk_ptr = bulk_tab_const; *get_bulk_ptr; get_bulk_ptr++) {
+
+ if (*keep_ptr < *get_bulk_ptr)
+ continue;
+
+ use_external_cache = external_cache;
+ use_constant_values = 1;
+ n_max_bulk = 0;
+ n_get_bulk = *get_bulk_ptr;
+ n_put_bulk = *get_bulk_ptr;
+ n_keep = *keep_ptr;
+ ret = launch_cores(mp, cores);
+ if (ret < 0)
+ return -1;
+ }
+ }
+
return 0;
}
@@ -449,22 +499,25 @@ do_all_mempool_perf_tests(unsigned int cores)
const char *mp_cache_ops;
const char *mp_nocache_ops;
const char *default_pool_ops;
+ unsigned int mempool_size = cores *
+ (MAX_KEEP + RTE_MEMPOOL_CACHE_MAX_SIZE * 2) - 1;
int ret = -1;
/* create a mempool (without cache) */
- mp_nocache = rte_mempool_create("perf_test_nocache", MEMPOOL_SIZE,
+ mp_nocache = rte_mempool_create("perf_test_nocache", mempool_size,
MEMPOOL_ELT_SIZE, 0, 0,
NULL, NULL,
my_obj_init, NULL,
SOCKET_ID_ANY, 0);
if (mp_nocache == NULL) {
printf("cannot allocate mempool (without cache)\n");
+ ret = TEST_SKIPPED;
goto err;
}
mp_nocache_ops = rte_mempool_get_ops(mp_nocache->ops_index)->name;
/* create a mempool (with cache) */
- mp_cache = rte_mempool_create("perf_test_cache", MEMPOOL_SIZE,
+ mp_cache = rte_mempool_create("perf_test_cache", mempool_size,
MEMPOOL_ELT_SIZE,
RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
NULL, NULL,
@@ -472,6 +525,7 @@ do_all_mempool_perf_tests(unsigned int cores)
SOCKET_ID_ANY, 0);
if (mp_cache == NULL) {
printf("cannot allocate mempool (with cache)\n");
+ ret = TEST_SKIPPED;
goto err;
}
mp_cache_ops = rte_mempool_get_ops(mp_cache->ops_index)->name;
@@ -480,12 +534,13 @@ do_all_mempool_perf_tests(unsigned int cores)
/* Create a mempool (without cache) based on Default handler */
default_pool_nocache = rte_mempool_create_empty("default_pool_nocache",
- MEMPOOL_SIZE,
+ mempool_size,
MEMPOOL_ELT_SIZE,
0, 0,
SOCKET_ID_ANY, 0);
if (default_pool_nocache == NULL) {
printf("cannot allocate %s mempool (without cache)\n", default_pool_ops);
+ ret = TEST_SKIPPED;
goto err;
}
if (rte_mempool_set_ops_byname(default_pool_nocache, default_pool_ops, NULL) < 0) {
@@ -494,18 +549,20 @@ do_all_mempool_perf_tests(unsigned int cores)
}
if (rte_mempool_populate_default(default_pool_nocache) < 0) {
printf("cannot populate %s mempool\n", default_pool_ops);
+ ret = TEST_SKIPPED;
goto err;
}
rte_mempool_obj_iter(default_pool_nocache, my_obj_init, NULL);
/* Create a mempool (with cache) based on Default handler */
default_pool_cache = rte_mempool_create_empty("default_pool_cache",
- MEMPOOL_SIZE,
+ mempool_size,
MEMPOOL_ELT_SIZE,
RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
SOCKET_ID_ANY, 0);
if (default_pool_cache == NULL) {
printf("cannot allocate %s mempool (with cache)\n", default_pool_ops);
+ ret = TEST_SKIPPED;
goto err;
}
if (rte_mempool_set_ops_byname(default_pool_cache, default_pool_ops, NULL) < 0) {
@@ -514,6 +571,7 @@ do_all_mempool_perf_tests(unsigned int cores)
}
if (rte_mempool_populate_default(default_pool_cache) < 0) {
printf("cannot populate %s mempool\n", default_pool_ops);
+ ret = TEST_SKIPPED;
goto err;
}
rte_mempool_obj_iter(default_pool_cache, my_obj_init, NULL);
@@ -584,27 +642,30 @@ test_mempool_perf_allcores(void)
static int
test_mempool_perf(void)
{
- int ret = -1;
-
- /* performance test with 1, 2 and max cores */
- if (do_all_mempool_perf_tests(1) < 0)
- goto err;
- if (rte_lcore_count() == 1)
- goto done;
-
- if (do_all_mempool_perf_tests(2) < 0)
- goto err;
- if (rte_lcore_count() == 2)
- goto done;
+ unsigned int cores = rte_lcore_count();
+ int ret;
- if (do_all_mempool_perf_tests(rte_lcore_count()) < 0)
- goto err;
+ /*
+ * Performance test with max, 1 and 2 cores.
+ *
+ * The largest configuration needs the most memory, so run it
+ * first: on a system which cannot fit it, the mempool allocation
+ * fails right away and the test is skipped without first spending
+ * minutes on the smaller core counts.
+ */
+ if (cores > 2) {
+ ret = do_all_mempool_perf_tests(cores);
+ if (ret != 0)
+ return ret;
+ }
-done:
- ret = 0;
+ ret = do_all_mempool_perf_tests(1);
+ if (ret != 0)
+ return ret;
+ if (cores == 1)
+ return 0;
-err:
- return ret;
+ return do_all_mempool_perf_tests(2);
}
REGISTER_PERF_TEST(mempool_perf_autotest, test_mempool_perf);
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* RE: [PATCH v2 5/5] app/test/mempool_perf: adjust test to work with many cores
2026-08-26 1:56 ` [PATCH v2 5/5] app/test/mempool_perf: adjust test to work with many cores Stephen Hemminger
@ 2026-08-26 3:58 ` Morten Brørup
0 siblings, 0 replies; 21+ messages in thread
From: Morten Brørup @ 2026-08-26 3:58 UTC (permalink / raw)
To: Stephen Hemminger, dev
Acked-by: Morten Brørup <mb@smartsharesystems.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2026-08-26 3:58 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-29 17:10 [PATCH 0/7] app/test: make perf tests usable on wider range of systems Stephen Hemminger
2026-05-29 17:10 ` [PATCH 1/7] app/test/reciprocal_division: make it a fast test Stephen Hemminger
2026-05-29 17:10 ` [PATCH 2/7] app/test/reciprocal_division_perf: reduce test time Stephen Hemminger
2026-05-29 17:10 ` [PATCH 3/7] app/test/mempool_perf: size mempool by tested cores Stephen Hemminger
2026-06-01 8:12 ` Andrew Rybchenko
2026-06-01 12:22 ` Morten Brørup
2026-05-29 17:10 ` [PATCH 4/7] app/test/mempool_perf: drop constant-values replay Stephen Hemminger
2026-06-01 8:34 ` Andrew Rybchenko
2026-06-01 13:22 ` Morten Brørup
2026-05-29 17:10 ` [PATCH 5/7] app/test/mempool_perf: scale down for high core counts Stephen Hemminger
2026-06-01 8:42 ` Andrew Rybchenko
2026-06-01 12:58 ` Morten Brørup
2026-05-29 17:10 ` [PATCH 6/7] app/test/test_rcu_qsbr_perf: call quiescent more often Stephen Hemminger
2026-05-29 17:11 ` [PATCH 7/7] app/test/test_pmd_perf: skip if no device available Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 0/5] app/test: make perf tests usable on wider range of systems Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 1/5] app/test/reciprocal_division: make it a fast test Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 2/5] app/test/reciprocal_division_perf: reduce test time Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 3/5] app/test/test_rcu_qsbr_perf: call quiescent more often Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 4/5] app/test/test_pmd_perf: skip if no device available Stephen Hemminger
2026-08-26 1:56 ` [PATCH v2 5/5] app/test/mempool_perf: adjust test to work with many cores Stephen Hemminger
2026-08-26 3:58 ` Morten Brørup
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox