From 8b3b90685ecd486ee794d7c6895c09b417fa427b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Mon, 2 Sep 2024 13:51:26 +0300 Subject: [PATCH] test: perf: random: add target test duration command line option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add option -t,--time, which can be used to set a target test duration per random data type. The default is 500 msec, so the default test duration is half a second times the number of available random data types. This saves about half a minute in some environments. Signed-off-by: Jere Leppänen Reviewed-by: Matias Elo --- test/performance/odp_random.c | 74 ++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/test/performance/odp_random.c b/test/performance/odp_random.c index 49c55e107b..7c96ae46e4 100644 --- a/test/performance/odp_random.c +++ b/test/performance/odp_random.c @@ -54,6 +54,7 @@ typedef struct { int num_threads; uint32_t size; uint32_t rounds; + uint32_t msec; uint64_t delay; } options_t; @@ -64,6 +65,7 @@ static const options_t options_def = { .num_threads = 1, .size = 256, .rounds = 100000, + .msec = 500, .delay = 0, }; @@ -81,11 +83,14 @@ static void print_usage(void) " -s, --size Size of buffer in bytes. Default %u.\n" " -r, --rounds Number of test rounds. Default %u.\n" " Divided by 100 for ODP_RANDOM_TRUE.\n" + " -t, --time Target test duration (msec). 0: use rounds from -r option. Default %u.\n" + " Based on a measurement on one thread. Test duration may be\n" + " significantly longer with multiple threads.\n" " -d, --delay Delay (nsec) between buffer fills. Default %" PRIu64 ".\n" " Affects only latency mode.\n" " -h, --help This help.\n" "\n", - options_def.size, options_def.rounds, options_def.delay); + options_def.size, options_def.rounds, options_def.msec, options_def.delay); } static int parse_options(int argc, char *argv[]) @@ -99,12 +104,13 @@ static int parse_options(int argc, char *argv[]) { "num_cpu", required_argument, NULL, 'c' }, { "size", required_argument, NULL, 's' }, { "rounds", required_argument, NULL, 'r' }, + { "time", required_argument, NULL, 't' }, { "delay", required_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 } }; - static const char *shortopts = "+m:c:s:r:d:h"; + static const char *shortopts = "+m:c:s:r:t:d:h"; options = options_def; options.size = 0; @@ -128,6 +134,9 @@ static int parse_options(int argc, char *argv[]) case 'r': options.rounds = atol(optarg); break; + case 't': + options.msec = atol(optarg); + break; case 'd': options.delay = atol(optarg); break; @@ -158,6 +167,7 @@ static int parse_options(int argc, char *argv[]) printf(" num_cpu: %i\n", options.num_threads); printf(" size: %u\n", options.size); printf(" rounds: %u\n", options.rounds); + printf(" time: %u\n", options.msec); printf(" delay: %" PRIu64 "\n", options.delay); printf("\n"); @@ -322,25 +332,69 @@ static int test_random_latency(void *ptr) return 0; } -static uint32_t type_rounds(odp_random_kind_t type) +static uint32_t type_rounds(test_global_t *global, odp_random_kind_t type) { - switch (type) { - case ODP_RANDOM_TRUE: - return options.rounds / 100; - default: - return options.rounds; + uint32_t rounds = options.rounds; + + if (type == ODP_RANDOM_TRUE) + rounds /= 100; + + if (options.msec) { + /* + * Determine number of rounds to run based on the target test + * duration. Random data may be very fast or very slow, so + * start with just one round and increase exponentially until + * we hit a time limit. Then use the total number of rounds we + * reached to calculate a suitable number of rounds for the + * actual test. + */ + + uint8_t *buf = (uint8_t *)malloc(options.size); + + if (!buf) { + ODPH_ERR("malloc() failed\n"); + exit(EXIT_FAILURE); + } + + /* One warm up round */ + random_data_loop(type, 1, buf, options.size); + + uint32_t r = 1, tr = 0; + odp_time_t time; + odp_time_t start_time = odp_time_local(); + odp_time_t end_time = odp_time_add_ns(start_time, 100 * ODP_TIME_MSEC_IN_NS); + + while (1) { + if (options.mode) + random_data_latency(global, 0, r, buf, options.size); + else + random_data_loop(type, r, buf, options.size); + tr += r; + time = odp_time_local(); + if (odp_time_cmp(time, end_time) >= 0) + break; + r *= 2; + } + + rounds = (uint64_t)tr * options.msec * ODP_TIME_MSEC_IN_NS / + odp_time_diff_ns(time, start_time); + free(buf); } + + return ODPH_MAX(1u, rounds); } static void test_type(odp_instance_t instance, test_global_t *global, odp_random_kind_t type) { int i; + uint32_t rounds; int num_threads = options.num_threads; - uint32_t rounds = type_rounds(type); uint32_t size = options.size; - memset(&global->stat, 0, sizeof(global->stat)); global->type = type; + rounds = type_rounds(global, type); + + memset(&global->stat, 0, sizeof(global->stat)); global->rounds = rounds; odp_barrier_init(&global->barrier, num_threads);