aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPetri Savolainen <petri.savolainen@nokia.com>2022-03-28 17:22:32 +0300
committerPetri Savolainen <petri.savolainen@nokia.com>2022-04-12 16:25:36 +0300
commit9f861eed679aafd4acbbd82a2525c76382522d38 (patch)
tree545bf7ae76b7fee13c01f8c1f04c3d02b20a9cf9 /test
parent8fb7cb36a93afc2e6cebd343974eb19c68efd880 (diff)
test: random: add latency test mode
Added new test mode which measure random number generation latency. Especially, latency of true random number generation may vary a lot depending on entropy collection status. New -m option is used to select between throughput and latency measurement modes. Additional delay may be added between buffer fills in latency mode with new -d option. Delay is not included into latency measurement, but affects throughput (MB/sec) results (in latency mode). Signed-off-by: Petri Savolainen <petri.savolainen@nokia.com> Reviewed-by: Tuomas Taipale <tuomas.taipale@nokia.com>
Diffstat (limited to 'test')
-rw-r--r--test/performance/odp_random.c180
1 files changed, 168 insertions, 12 deletions
diff --git a/test/performance/odp_random.c b/test/performance/odp_random.c
index f2f041a5a..46134ac0c 100644
--- a/test/performance/odp_random.c
+++ b/test/performance/odp_random.c
@@ -37,21 +37,29 @@ struct test_global_t {
struct {
uint64_t nsec[ODP_THREAD_COUNT_MAX];
+ uint64_t sum[ODP_THREAD_COUNT_MAX];
+ uint64_t min[ODP_THREAD_COUNT_MAX];
+ uint64_t max[ODP_THREAD_COUNT_MAX];
} stat;
};
/* Command line options */
typedef struct {
+ int mode;
int num_threads;
uint32_t size;
uint32_t rounds;
+ uint64_t delay;
+
} options_t;
static options_t options;
static const options_t options_def = {
+ .mode = 0,
.num_threads = 1,
.size = 256,
.rounds = 100000,
+ .delay = 0,
};
static void print_usage(void)
@@ -61,13 +69,18 @@ static void print_usage(void)
"\n"
"Usage: odp_random [options]\n"
"\n"
+ " -m, --mode Test mode select (default: 0):\n"
+ " 0: Data throughput\n"
+ " 1: Data generation latency (size: 8B by default)\n"
" -t, --threads Number of worker threads (default %u)\n"
" -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"
+ " -d, --delay Delay (nsec) between buffer fills (default %" PRIu64 ").\n"
+ " Affects only latency mode.\n"
" -h, --help This help\n"
"\n",
- options_def.num_threads, options_def.size, options_def.rounds);
+ options_def.num_threads, options_def.size, options_def.rounds, options_def.delay);
}
static int parse_options(int argc, char *argv[])
@@ -77,16 +90,19 @@ static int parse_options(int argc, char *argv[])
int ret = 0;
static const struct option longopts[] = {
+ { "mode", required_argument, NULL, 'm' },
{ "threads", required_argument, NULL, 't' },
{ "size", required_argument, NULL, 's' },
{ "rounds", required_argument, NULL, 'r' },
+ { "delay", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ NULL, 0, NULL, 0 }
};
- static const char *shortopts = "+t:s:r:h";
+ static const char *shortopts = "+m:t:s:r:d:h";
options = options_def;
+ options.size = 0;
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
@@ -95,6 +111,9 @@ static int parse_options(int argc, char *argv[])
break;
switch (opt) {
+ case 'm':
+ options.mode = atoi(optarg);
+ break;
case 't':
options.num_threads = atol(optarg);
break;
@@ -104,6 +123,9 @@ static int parse_options(int argc, char *argv[])
case 'r':
options.rounds = atol(optarg);
break;
+ case 'd':
+ options.delay = atol(optarg);
+ break;
case 'h':
/* fall through */
default:
@@ -113,11 +135,27 @@ static int parse_options(int argc, char *argv[])
}
}
- if (options.size < 1) {
- ODPH_ERR("Invalid size: %" PRIu32 "\n", options.size);
+ if (options.num_threads < 1 || options.num_threads > ODP_THREAD_COUNT_MAX) {
+ ODPH_ERR("Bad number of threads: %i\n", options.num_threads);
return -1;
}
+ if (options.size == 0) {
+ options.size = options_def.size;
+
+ if (options.mode)
+ options.size = 8;
+ }
+
+ printf("\nOptions:\n");
+ printf("------------------------\n");
+ printf(" mode: %i\n", options.mode);
+ printf(" threads: %i\n", options.num_threads);
+ printf(" size: %u\n", options.size);
+ printf(" rounds: %u\n", options.rounds);
+ printf(" delay: %" PRIu64 "\n", options.delay);
+ printf("\n");
+
return ret;
}
@@ -191,6 +229,94 @@ static int test_random_perf(void *ptr)
return 0;
}
+static inline void random_data_latency(test_global_t *global, int thread_idx,
+ uint32_t rounds, uint8_t *data, uint32_t size)
+{
+ uint32_t i;
+ int32_t ret;
+ odp_time_t t1, t2, start;
+ uint64_t nsec;
+ odp_random_kind_t type = global->type;
+ uint64_t delay = options.delay;
+ uint64_t min = UINT64_MAX;
+ uint64_t max = 0;
+ uint64_t sum = 0;
+ uint64_t seed = 0;
+
+ start = odp_time_local();
+
+ for (i = 0; i < rounds; i++) {
+ uint32_t pos = 0;
+
+ if (delay)
+ odp_time_wait_ns(delay);
+
+ if ((int)type == PSEUDO_RANDOM) {
+ t1 = odp_time_local_strict();
+ while (pos < size) {
+ ret = odp_random_test_data(data + pos, size - pos, &seed);
+
+ if (ret < 0) {
+ ODPH_ERR("odp_random_test_data() failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ pos += ret;
+ }
+ t2 = odp_time_local_strict();
+ } else {
+ t1 = odp_time_local_strict();
+ while (pos < size) {
+ ret = odp_random_data(data + pos, size - pos, type);
+
+ if (ret < 0) {
+ ODPH_ERR("odp_random_data() failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ pos += ret;
+ }
+ t2 = odp_time_local_strict();
+ }
+
+ nsec = odp_time_diff_ns(t2, t1);
+ sum += nsec;
+
+ if (nsec > max)
+ max = nsec;
+ if (nsec < min)
+ min = nsec;
+ }
+
+ nsec = odp_time_diff_ns(odp_time_local(), start);
+
+ global->stat.nsec[thread_idx] = nsec;
+ global->stat.sum[thread_idx] = sum;
+ global->stat.min[thread_idx] = min;
+ global->stat.max[thread_idx] = max;
+}
+
+static int test_random_latency(void *ptr)
+{
+ thread_arg_t *thread_arg = ptr;
+ test_global_t *global = thread_arg->global;
+ odp_random_kind_t type = global->type;
+ int thread_idx = thread_arg->thread_idx;
+ uint8_t *data = thread_arg->data;
+ uint32_t size = options.size;
+ uint32_t rounds = global->rounds;
+
+ /* One warm up round */
+ random_data_loop(type, 1, data, size);
+
+ odp_barrier_wait(&global->barrier);
+
+ /* Test run */
+ random_data_latency(global, thread_idx, rounds, data, size);
+
+ return 0;
+}
+
static uint32_t type_rounds(odp_random_kind_t type)
{
switch (type) {
@@ -206,6 +332,7 @@ static void test_type(odp_instance_t instance, test_global_t *global, odp_random
int i;
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;
@@ -229,8 +356,12 @@ static void test_type(odp_instance_t instance, test_global_t *global, odp_random
for (i = 0; i < num_threads; i++) {
odph_thread_param_init(&thr_param[i]);
thr_param[i].thr_type = ODP_THREAD_WORKER;
- thr_param[i].start = test_random_perf;
thr_param[i].arg = &global->thread_arg[i];
+
+ if (options.mode == 0)
+ thr_param[i].start = test_random_perf;
+ else
+ thr_param[i].start = test_random_latency;
}
memset(&thr_worker, 0, sizeof(thr_worker));
@@ -247,7 +378,7 @@ static void test_type(odp_instance_t instance, test_global_t *global, odp_random
double mb, seconds, nsec = 0;
- for (i = 0; i < ODP_THREAD_COUNT_MAX; i++)
+ for (i = 0; i < num_threads; i++)
nsec += global->stat.nsec[i];
nsec /= num_threads;
@@ -267,16 +398,41 @@ static void test_type(odp_instance_t instance, test_global_t *global, odp_random
}
printf("--------------------\n");
- printf("threads: %d size: %u B rounds: %u ", num_threads,
- options.size, rounds);
- mb = (uint64_t)num_threads * (uint64_t)options.size *
- (uint64_t)rounds;
+ printf("threads: %d size: %u B rounds: %u ", num_threads, size, rounds);
+ mb = (uint64_t)num_threads * (uint64_t)size * (uint64_t)rounds;
mb /= MB;
seconds = (double)nsec / (double)ODP_TIME_SEC_IN_NS;
printf("MB: %.3f seconds: %.3f ", mb, seconds);
printf("MB/s: %.3f ", mb / seconds);
- printf("MB/s/thread: %.3f", mb / seconds / (double)num_threads);
- printf("\n\n");
+ printf("MB/s/thread: %.3f\n", mb / seconds / (double)num_threads);
+
+ if (options.mode) {
+ double ave;
+ uint64_t min = UINT64_MAX;
+ uint64_t max = 0;
+ uint64_t sum = 0;
+
+ printf(" latency (nsec)\n");
+ printf(" thread min max ave\n");
+ for (i = 0; i < num_threads; i++) {
+ ave = (double)global->stat.sum[i] / rounds;
+ sum += global->stat.sum[i];
+
+ if (global->stat.min[i] < min)
+ min = global->stat.min[i];
+
+ if (global->stat.max[i] > max)
+ max = global->stat.max[i];
+
+ printf("%8i %8" PRIu64 " %8" PRIu64 " %10.1f\n", i, global->stat.min[i],
+ global->stat.max[i], ave);
+ }
+
+ printf(" all %8" PRIu64 " %8" PRIu64 " %10.1f\n",
+ min, max, ((double)sum / rounds) / num_threads);
+ }
+
+ printf("\n");
}
int main(int argc, char **argv)