From bc564e7465ded371e6014111deb1919024b76735 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Wed, 9 Sep 2026 16:19:20 +0200 Subject: [PATCH] Improve speed benchmark stability with adaptive 1 ms sampling and best-result selection --- cmdline/speed.c | 100 ++++++++++++++++++------------------------ raid/test/speedtest.c | 75 ++++++++++++++----------------- 2 files changed, 74 insertions(+), 101 deletions(-) diff --git a/cmdline/speed.c b/cmdline/speed.c index 91cb5290..c690986e 100644 --- a/cmdline/speed.c +++ b/cmdline/speed.c @@ -24,28 +24,33 @@ static int64_t diffgettimeofday(struct timeval* start, struct timeval* stop) return d; } -/** - * Start time measurement. - */ -/* INDENT-OFF */ #define SPEED_START \ - count = 0; \ - gettimeofday(&start, 0); \ - do { \ - for (i = 0; i < delta; ++i) -/* INDENT-ON */ + { \ + int speed_delta_ = delta; \ + int64_t elapsed_ = 0; \ + int64_t best_dt_ = INT64_MAX; \ + do { \ + struct timeval start; \ + struct timeval stop; \ + gettimeofday(&start, 0); \ + for (int i_ = 0; i_ < speed_delta_; ++i_) -/** - * Stop time measurement. - */ -/* INDENT-OFF */ #define SPEED_STOP \ - count += delta; \ gettimeofday(&stop, 0); \ - } while (diffgettimeofday(&start, &stop) < period * 1000LL); \ - ds = size * (int64_t)count * nd; \ - dt = diffgettimeofday(&start, &stop); -/* INDENT-ON */ + dt = diffgettimeofday(&start, &stop); \ + if (dt < 1000 && speed_delta_ <= INT_MAX / 2) { \ + speed_delta_ *= 2; \ + elapsed_ = 0; \ + best_dt_ = INT64_MAX; \ + continue; \ + } \ + elapsed_ += dt; \ + if (dt < best_dt_) \ + best_dt_ = dt; \ + } while (elapsed_ < period * 1000LL); \ + ds = size * (int64_t)speed_delta_ * nd; \ + dt = best_dt_; \ + } /** * Global variable used to propagate side effects. @@ -57,20 +62,17 @@ unsigned side_effect; void speed_mem(int nd, void** v, int size, int delta, int period) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; - int i, j; - int count; + int i; printf("Memory write speed using the C memset() function:\n"); printf("%8s", "memset"); fflush(stdout); SPEED_START { - for (j = 0; j < nd; ++j) - memset(v[j], j, size); + for (i = 0; i < nd; ++i) + memset(v[i], i, size); } SPEED_STOP printf("%8" PRIu64, ds / dt); @@ -80,12 +82,9 @@ void speed_mem(int nd, void** v, int size, int delta, int period) void speed_crc(int nd, void** v, int size, int delta, int period) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; - int i, j; - int count; + int i; /* crc table */ printf("CRC used to check the content file integrity:\n"); @@ -94,8 +93,8 @@ void speed_crc(int nd, void** v, int size, int delta, int period) fflush(stdout); SPEED_START { - for (j = 0; j < nd; ++j) - side_effect += crc32c_gen(0, v[j], size); + for (i = 0; i < nd; ++i) + side_effect += crc32c_gen(0, v[i], size); } SPEED_STOP printf("%8" PRIu64, ds / dt); @@ -107,8 +106,8 @@ void speed_crc(int nd, void** v, int size, int delta, int period) fflush(stdout); SPEED_START { - for (j = 0; j < nd; ++j) - side_effect += crc32c_x86(0, v[j], size); + for (i = 0; i < nd; ++i) + side_effect += crc32c_x86(0, v[i], size); } SPEED_STOP printf("%8" PRIu64, ds / dt); @@ -121,8 +120,8 @@ void speed_crc(int nd, void** v, int size, int delta, int period) fflush(stdout); SPEED_START { - for (j = 0; j < nd; ++j) - side_effect += crc32c_arm64(0, v[j], size); + for (i = 0; i < nd; ++i) + side_effect += crc32c_arm64(0, v[i], size); } SPEED_STOP printf("%8" PRIu64, ds / dt); @@ -134,12 +133,9 @@ void speed_crc(int nd, void** v, int size, int delta, int period) void speed_hash(int nd, void** v, int size, int delta, int period) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; - int i, j; - int count; + int i; unsigned char digest[HASH_MAX]; unsigned char seed[HASH_MAX]; @@ -162,24 +158,24 @@ void speed_hash(int nd, void** v, int size, int delta, int period) fflush(stdout); SPEED_START { - for (j = 0; j < nd; ++j) - memhash(HASH_MURMUR3, seed, digest, v[j], size); + for (i = 0; i < nd; ++i) + memhash(HASH_MURMUR3, seed, digest, v[i], size); } SPEED_STOP printf("%8" PRIu64, ds / dt); fflush(stdout); SPEED_START { - for (j = 0; j < nd; ++j) - memhash(HASH_SPOOKY2, seed, digest, v[j], size); + for (i = 0; i < nd; ++i) + memhash(HASH_SPOOKY2, seed, digest, v[i], size); } SPEED_STOP printf("%8" PRIu64, ds / dt); fflush(stdout); SPEED_START { - for (j = 0; j < nd; ++j) - memhash(HASH_MUSEAIR, seed, digest, v[j], size); + for (i = 0; i < nd; ++i) + memhash(HASH_MUSEAIR, seed, digest, v[i], size); } SPEED_STOP printf("%8" PRIu64, ds / dt); @@ -189,12 +185,8 @@ void speed_hash(int nd, void** v, int size, int delta, int period) void speed_gen(int nd, void** v, int size, int delta, int period, const char* msg) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; - int i; - int count; int mode = raid_mode(RAID_MODE_GET); /* RAID table */ @@ -1076,12 +1068,8 @@ void speed_gen(int nd, void** v, int size, int delta, int period, const char* ms void speed_genz(int nd, void** v, int size, int delta, int period) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; - int i; - int count; /* Vandermonde table */ printf("Vandermonde functions used for computing parity with 'sync':\n"); @@ -1199,12 +1187,9 @@ void speed_genz(int nd, void** v, int size, int delta, int period) void speed_rec(int nd, void** v, int size, int delta, int period) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; int i; - int count; int id[RAID_PARITY_MAX]; int ip[RAID_PARITY_MAX]; @@ -2358,9 +2343,8 @@ void speed(int period, int nd, int size) else size *= KIBI; if (period < 1) - period = 1000; - - delta = period >= 1000 ? 10 : 1; + period = 250; + delta = 1; /* auto increased in SPEED_START */ nv = nd + RAID_PARITY_MAX; diff --git a/raid/test/speedtest.c b/raid/test/speedtest.c index a4a1893d..1eb03a91 100644 --- a/raid/test/speedtest.c +++ b/raid/test/speedtest.c @@ -10,11 +10,16 @@ #include #include #include +#include /* * Size of the blocks to test. */ +#ifdef COVERAGE +#define TEST_SIZE (4 * 1024) +#else #define TEST_SIZE (256 * 1024) +#endif /* * Number of data blocks to test. @@ -34,52 +39,47 @@ static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop) return d; } -/** - * Test period. - */ -#ifdef COVERAGE -#define TEST_PERIOD 100000LL -#define TEST_DELTA 1 -#else -#define TEST_PERIOD 1000000LL -#define TEST_DELTA 10 -#endif - -/** - * Start time measurement. - */ #define SPEED_START \ - count = 0; \ - gettimeofday(&start, 0); \ + { \ + int speed_delta_ = delta; \ + int64_t elapsed_ = 0; \ + int64_t best_dt_ = INT64_MAX; \ do { \ - for (i = 0; i < delta; ++i) + struct timeval start; \ + struct timeval stop; \ + gettimeofday(&start, 0); \ + for (int i_ = 0; i_ < speed_delta_; ++i_) -/** - * Stop time measurement. - */ #define SPEED_STOP \ - count += delta; \ gettimeofday(&stop, 0); \ - } while (diffgettimeofday(&start, &stop) < period); \ - ds = size * (int64_t)count * nd; \ - dt = diffgettimeofday(&start, &stop); + dt = diffgettimeofday(&start, &stop); \ + if (dt < 1000 && speed_delta_ <= INT_MAX / 2) { \ + speed_delta_ *= 2; \ + elapsed_ = 0; \ + best_dt_ = INT64_MAX; \ + continue; \ + } \ + elapsed_ += dt; \ + if (dt < best_dt_) \ + best_dt_ = dt; \ + } while (elapsed_ < period * 1000LL); \ + ds = size * (int64_t)speed_delta_ * nd; \ + dt = best_dt_; \ + } void speed_mem(int nd, void **v, int size, int delta, int period) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; - int i, j; - int count; + int i; printf("Memory write speed using the C memset() function:\n"); printf("%8s", "memset"); fflush(stdout); SPEED_START { - for (j = 0; j < nd; ++j) - memset(v[j], j, size); + for (i = 0; i < nd; ++i) + memset(v[i], i, size); } SPEED_STOP printf("%8" PRIu64, ds / dt); @@ -89,12 +89,8 @@ void speed_mem(int nd, void **v, int size, int delta, int period) void speed_gen(int nd, void **v, int size, int delta, int period, const char *msg) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; - int i; - int count; int mode = raid_mode(RAID_MODE_GET); /* RAID table */ @@ -972,12 +968,8 @@ void speed_gen(int nd, void **v, int size, int delta, int period, const char *ms void speed_genz(int nd, void **v, int size, int delta, int period) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; - int i; - int count; /* Vandermonde table */ printf("Vandermonde functions used for computing the parity:\n"); @@ -1095,14 +1087,11 @@ void speed_genz(int nd, void **v, int size, int delta, int period) void speed_rec(int nd, void **v, int size, int delta, int period) { - struct timeval start; - struct timeval stop; int64_t ds; int64_t dt; int i; int id[RAID_PARITY_MAX]; int ip[RAID_PARITY_MAX]; - int count; /* basic disks and parity mapping */ for (i = 0; i < RAID_PARITY_MAX; ++i) { @@ -2138,8 +2127,8 @@ void speed(void) void **v; int i; int size = TEST_SIZE; - int delta = TEST_DELTA; - int period = TEST_PERIOD; + int period = 250; + int delta = 1; /* auto increased in SPEED_START */ nv = nd + RAID_PARITY_MAX;