17#include <odp/helper/odph_api.h>
19#include <bench_common.h>
20#include <export_results.h>
28#define TEST_MAX_BURST 32U
29#define TEST_DEF_BURST 8U
30#define TEST_REPEAT_COUNT 1000U
31#define TEST_ROUNDS 100U
32#define TEST_MAX_QUEUES (32U * 1024U)
33#define TEST_MAX_BENCH 40U
34#define TEST_MAX_DATA_ARR (TEST_MAX_BURST * TEST_REPEAT_COUNT)
36#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
37 strrchr((file_name), '/') + 1 : (file_name))
39#define BENCH_INFO_1(run_fn, init_fn, term_fn) \
40 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .desc = NULL}
42#define BENCH_INFO_2(fn_name, run_fn, init_fn, term_fn) \
43 {.name = fn_name, .run = run_fn, .init = init_fn, .term = term_fn, .desc = NULL}
45#define BENCH_INFO_TM_1(run_fn, init_fn, term_fn) \
46 {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .cond = NULL,\
49#define BENCH_INFO_TM_2(fn_name, run_fn, init_fn, term_fn) \
50 {.name = fn_name, .run = run_fn, .init = init_fn, .term = term_fn, .cond = NULL,\
81 void *ptrs[TEST_MAX_DATA_ARR];
93 int (*suite_fn)(
void *args);
94 int (*export_fn)(
void *data);
97 double b[TEST_MAX_BENCH];
98 bench_tm_result_t t[TEST_MAX_BENCH];
102 uint8_t context[ODP_CACHE_LINE_SIZE];
105static args_t *gbl_args;
107static void init_src_events(
void)
110 const uint32_t num = gbl_args->resources.num_buf;
113 for (i = 0U; i < num; i++) {
119 ODPH_ABORT(
"Failed to allocate\n");
124 for (uint32_t j = i; j < ODPH_ARRAY_SIZE(gbl_args->data.evs); j++)
128static void term_partial_events(uint32_t start_idx)
132 for (uint32_t i = start_idx; i < ODPH_ARRAY_SIZE(gbl_args->data.evs); i++) {
133 ev = gbl_args->data.evs[i];
140static void term_src_events(
void)
155 term_partial_events(i);
158static void init_events(
void)
160 for (uint32_t i = 0U; i < ODPH_ARRAY_SIZE(gbl_args->data.evs); i++)
164static void fill_plain_queues(
void)
166 const uint32_t num = gbl_args->resources.num_buf;
170 for (uint32_t i = 0U; i < num; i++) {
176 ODPH_ABORT(
"Failed to allocate\n");
181 ODPH_ABORT(
"Failed to enqueue\n");
187static void term_events(
void)
191 for (uint32_t i = 0U; i < ODPH_ARRAY_SIZE(gbl_args->data.evs); i++) {
192 ev = gbl_args->data.evs[i];
199static void term_dst_events(
void)
215static void fill_scheduled_queues(
void)
217 const uint32_t num = gbl_args->resources.num_buf;
221 for (uint32_t i = 0U; i < num; i++) {
227 ODPH_ABORT(
"Failed to allocate\n");
232 ODPH_ABORT(
"Failed to enqueue\n");
238static void term_scheduled_src_events(
void)
253 term_partial_events(i);
256static void term_scheduled_dst_events(
void)
272static int queue_context_set_plain(
void)
275 uint8_t *context = gbl_args->context;
276 const uint32_t len = ODPH_ARRAY_SIZE(gbl_args->context);
279 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
285static int queue_context_set_plain_tm(bench_tm_result_t *res,
int repeat_count)
287 bench_tm_stamp_t s1, s2;
289 uint8_t *context = gbl_args->context;
290 const uint32_t len = ODPH_ARRAY_SIZE(gbl_args->context);
292 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_context_set()");
294 for (
int i = 0U; i < repeat_count; i++) {
295 bench_tm_now(res, &s1);
297 bench_tm_now(res, &s2);
298 bench_tm_func_record(&s2, &s1, res, id1);
304static int queue_context_plain(
void)
307 void **dst = gbl_args->data.ptrs;
309 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
315static int queue_context_plain_tm(bench_tm_result_t *res,
int repeat_count)
317 bench_tm_stamp_t s1, s2;
319 void **dst = gbl_args->data.ptrs;
320 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_context()");
322 for (
int i = 0U; i < repeat_count; i++) {
323 bench_tm_now(res, &s1);
325 bench_tm_now(res, &s2);
326 bench_tm_func_record(&s2, &s1, res, id1);
332static int queue_context_set_scheduled(
void)
335 uint8_t *context = gbl_args->context;
336 const uint32_t len = ODPH_ARRAY_SIZE(gbl_args->context);
339 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
345static int queue_context_set_scheduled_tm(bench_tm_result_t *res,
int repeat_count)
347 bench_tm_stamp_t s1, s2;
349 uint8_t *context = gbl_args->context;
350 const uint32_t len = ODPH_ARRAY_SIZE(gbl_args->context);
352 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_context_set()");
354 for (
int i = 0U; i < repeat_count; i++) {
355 bench_tm_now(res, &s1);
357 bench_tm_now(res, &s2);
358 bench_tm_func_record(&s2, &s1, res, id1);
364static int queue_context_scheduled(
void)
367 void **dst = gbl_args->data.ptrs;
369 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
375static int queue_context_scheduled_tm(bench_tm_result_t *res,
int repeat_count)
377 bench_tm_stamp_t s1, s2;
379 void **dst = gbl_args->data.ptrs;
380 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_context()");
382 for (
int i = 0U; i < repeat_count; i++) {
383 bench_tm_now(res, &s1);
385 bench_tm_now(res, &s2);
386 bench_tm_func_record(&s2, &s1, res, id1);
392static int queue_enq_plain(
void)
398 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
404static int queue_enq_plain_tm(bench_tm_result_t *res,
int repeat_count)
406 bench_tm_stamp_t s1, s2;
410 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_enq()");
412 for (
int i = 0; i < repeat_count; i++) {
413 bench_tm_now(res, &s1);
415 bench_tm_now(res, &s2);
416 bench_tm_func_record(&s2, &s1, res, id1);
422static int queue_enq_multi_plain(
void)
426 int num_tot = 0, ret;
427 const int num_burst = gbl_args->appl.burst_size;
429 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++) {
432 ODPH_ASSERT(ret >= 0);
440static int queue_enq_multi_plain_tm(bench_tm_result_t *res,
int repeat_count)
442 bench_tm_stamp_t s1, s2;
445 int num_tot = 0, ret;
446 const int num_burst = gbl_args->appl.burst_size;
447 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_enq_multi()");
449 for (
int i = 0; i < repeat_count; i++) {
450 bench_tm_now(res, &s1);
452 bench_tm_now(res, &s2);
454 ODPH_ASSERT(ret >= 0);
456 bench_tm_func_record(&s2, &s1, res, id1);
463static int queue_deq_plain(
void)
468 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
474static int queue_deq_plain_tm(bench_tm_result_t *res,
int repeat_count)
476 bench_tm_stamp_t s1, s2;
479 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_deq()");
481 for (
int i = 0U; i < repeat_count; i++) {
482 bench_tm_now(res, &s1);
484 bench_tm_now(res, &s2);
485 bench_tm_func_record(&s2, &s1, res, id1);
491static int queue_deq_multi_plain(
void)
495 int num_tot = 0, ret;
496 const int num_burst = gbl_args->appl.burst_size;
498 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++) {
501 ODPH_ASSERT(ret >= 0);
509static int queue_deq_multi_plain_tm(bench_tm_result_t *res,
int repeat_count)
511 bench_tm_stamp_t s1, s2;
514 int num_tot = 0, ret;
515 const int num_burst = gbl_args->appl.burst_size;
516 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_deq_multi()");
518 for (
int i = 0U; i < repeat_count; i++) {
519 bench_tm_now(res, &s1);
521 bench_tm_now(res, &s2);
523 ODPH_ASSERT(ret >= 0);
525 bench_tm_func_record(&s2, &s1, res, id1);
532static int queue_enq_scheduled(
void)
538 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
544static int queue_enq_scheduled_tm(bench_tm_result_t *res,
int repeat_count)
546 bench_tm_stamp_t s1, s2;
550 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_enq()");
552 for (
int i = 0; i < repeat_count; i++) {
553 bench_tm_now(res, &s1);
555 bench_tm_now(res, &s2);
556 bench_tm_func_record(&s2, &s1, res, id1);
562static int queue_enq_multi_scheduled(
void)
566 int num_tot = 0, ret;
567 const int num_burst = gbl_args->appl.burst_size;
569 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++) {
572 ODPH_ASSERT(ret >= 0);
580static int queue_enq_multi_scheduled_tm(bench_tm_result_t *res,
int repeat_count)
582 bench_tm_stamp_t s1, s2;
585 int num_tot = 0, ret;
586 const int num_burst = gbl_args->appl.burst_size;
587 const uint8_t id1 = bench_tm_func_register(res,
"odp_queue_enq_multi()");
589 for (
int i = 0; i < repeat_count; i++) {
590 bench_tm_now(res, &s1);
592 bench_tm_now(res, &s2);
594 ODPH_ASSERT(ret >= 0);
596 bench_tm_func_record(&s2, &s1, res, id1);
603static int schedule(
void)
607 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
613static int schedule_tm(bench_tm_result_t *res,
int repeat_count)
615 bench_tm_stamp_t s1, s2;
617 const uint8_t id1 = bench_tm_func_register(res,
"odp_schedule()");
619 for (
int i = 0; i < repeat_count; i++) {
620 bench_tm_now(res, &s1);
622 bench_tm_now(res, &s2);
623 bench_tm_func_record(&s2, &s1, res, id1);
629static int schedule_prefetch_single(
void)
631 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
637static int schedule_prefetch_single_tm(bench_tm_result_t *res,
int repeat_count)
639 bench_tm_stamp_t s1, s2;
640 const uint8_t id1 = bench_tm_func_register(res,
"odp_schedule_prefetch(1)");
642 for (
int i = 0; i < repeat_count; i++) {
643 bench_tm_now(res, &s1);
645 bench_tm_now(res, &s2);
646 bench_tm_func_record(&s2, &s1, res, id1);
652static int schedule_multi_no_wait(
void)
655 const int num_burst = gbl_args->appl.burst_size;
658 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
664static int schedule_multi_wait(
void)
667 const int num_burst = gbl_args->appl.burst_size;
670 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
676static int schedule_multi_no_wait_tm(bench_tm_result_t *res,
int repeat_count)
678 bench_tm_stamp_t s1, s2;
680 const int num_burst = gbl_args->appl.burst_size;
682 const uint8_t id1 = bench_tm_func_register(res,
"odp_schedule_multi_no_wait()");
684 for (
int i = 0; i < repeat_count; i++) {
685 bench_tm_now(res, &s1);
687 bench_tm_now(res, &s2);
688 bench_tm_func_record(&s2, &s1, res, id1);
694static int schedule_multi_wait_tm(bench_tm_result_t *res,
int repeat_count)
696 bench_tm_stamp_t s1, s2;
698 const int num_burst = gbl_args->appl.burst_size;
700 const uint8_t id1 = bench_tm_func_register(res,
"odp_schedule_multi_wait()");
702 for (
int i = 0; i < repeat_count; i++) {
703 bench_tm_now(res, &s1);
705 bench_tm_now(res, &s2);
706 bench_tm_func_record(&s2, &s1, res, id1);
712static int schedule_multi(
void)
715 const int num_burst = gbl_args->appl.burst_size;
718 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
724static int schedule_multi_tm(bench_tm_result_t *res,
int repeat_count)
726 bench_tm_stamp_t s1, s2;
728 const int num_burst = gbl_args->appl.burst_size;
730 const uint8_t id1 = bench_tm_func_register(res,
"odp_schedule_multi()");
732 for (
int i = 0; i < repeat_count; i++) {
733 bench_tm_now(res, &s1);
735 bench_tm_now(res, &s2);
736 bench_tm_func_record(&s2, &s1, res, id1);
742static int schedule_prefetch_burst(
void)
744 const int num_burst = gbl_args->appl.burst_size;
746 for (uint32_t i = 0U; i < TEST_REPEAT_COUNT; i++)
752static int schedule_prefetch_burst_tm(bench_tm_result_t *res,
int repeat_count)
754 bench_tm_stamp_t s1, s2;
755 const int num_burst = gbl_args->appl.burst_size;
756 const uint8_t id1 = bench_tm_func_register(res,
"odp_schedule_prefetch(burst)");
758 for (
int i = 0; i < repeat_count; i++) {
759 bench_tm_now(res, &s1);
761 bench_tm_now(res, &s2);
762 bench_tm_func_record(&s2, &s1, res, id1);
768bench_info_t test_suite[] = {
769 BENCH_INFO_1(queue_context_set_plain, NULL, NULL),
770 BENCH_INFO_1(queue_context_plain, NULL, NULL),
771 BENCH_INFO_1(queue_context_set_scheduled, NULL, NULL),
772 BENCH_INFO_1(queue_context_scheduled, NULL, NULL),
773 BENCH_INFO_1(queue_enq_plain, init_src_events, term_src_events),
774 BENCH_INFO_1(queue_enq_multi_plain, init_src_events, term_src_events),
775 BENCH_INFO_1(queue_deq_plain, fill_plain_queues, term_dst_events),
776 BENCH_INFO_1(queue_deq_multi_plain, fill_plain_queues, term_dst_events),
777 BENCH_INFO_1(queue_enq_scheduled, init_src_events, term_scheduled_src_events),
778 BENCH_INFO_1(queue_enq_multi_scheduled, init_src_events, term_scheduled_src_events),
779 BENCH_INFO_2(
"schedule_empty", schedule, init_events, term_events),
780 BENCH_INFO_2(
"schedule_multi_no_wait_empty", schedule_multi_no_wait, init_events,
782 BENCH_INFO_2(
"schedule_multi_empty", schedule_multi, init_events, term_events),
783 BENCH_INFO_2(
"schedule_full", schedule, fill_scheduled_queues, term_scheduled_dst_events),
784 BENCH_INFO_2(
"schedule_multi_no_wait_full", schedule_multi_no_wait, fill_scheduled_queues,
785 term_scheduled_dst_events),
786 BENCH_INFO_2(
"schedule_multi_wait_full", schedule_multi_wait, fill_scheduled_queues,
787 term_scheduled_dst_events),
788 BENCH_INFO_2(
"schedule_multi_full", schedule_multi, fill_scheduled_queues,
789 term_scheduled_dst_events),
790 BENCH_INFO_2(
"schedule_prefetch_single", schedule_prefetch_single, fill_scheduled_queues,
791 term_scheduled_dst_events),
792 BENCH_INFO_2(
"schedule_prefetch_burst", schedule_prefetch_burst, fill_scheduled_queues,
793 term_scheduled_dst_events),
797 "Result array is too small to hold all the results");
799bench_tm_info_t test_suite_tm[] = {
800 BENCH_INFO_TM_1(queue_context_set_plain_tm, NULL, NULL),
801 BENCH_INFO_TM_1(queue_context_plain_tm, NULL, NULL),
802 BENCH_INFO_TM_1(queue_context_set_scheduled_tm, NULL, NULL),
803 BENCH_INFO_TM_1(queue_context_scheduled_tm, NULL, NULL),
804 BENCH_INFO_TM_1(queue_enq_plain_tm, init_src_events, term_src_events),
805 BENCH_INFO_TM_1(queue_enq_multi_plain_tm, init_src_events, term_src_events),
806 BENCH_INFO_TM_1(queue_deq_plain_tm, fill_plain_queues, term_dst_events),
807 BENCH_INFO_TM_1(queue_deq_multi_plain_tm, fill_plain_queues, term_dst_events),
808 BENCH_INFO_TM_1(queue_enq_scheduled_tm, init_src_events, term_scheduled_src_events),
809 BENCH_INFO_TM_1(queue_enq_multi_scheduled_tm, init_src_events, term_scheduled_src_events),
810 BENCH_INFO_TM_2(
"schedule_empty_tm", schedule_tm, init_events, term_events),
811 BENCH_INFO_TM_2(
"schedule_multi_no_wait_empty_tm", schedule_multi_no_wait_tm, init_events,
813 BENCH_INFO_TM_2(
"schedule_multi_empty_tm", schedule_multi_tm, init_events, term_events),
814 BENCH_INFO_TM_2(
"schedule_full_tm", schedule_tm, fill_scheduled_queues,
815 term_scheduled_dst_events),
816 BENCH_INFO_TM_2(
"schedule_multi_no_wait_full_tm", schedule_multi_no_wait_tm,
817 fill_scheduled_queues, term_scheduled_dst_events),
818 BENCH_INFO_TM_2(
"schedule_multi_wait_full_tm", schedule_multi_wait_tm,
819 fill_scheduled_queues, term_scheduled_dst_events),
820 BENCH_INFO_TM_2(
"schedule_multi_full_tm", schedule_multi_tm, fill_scheduled_queues,
821 term_scheduled_dst_events),
822 BENCH_INFO_TM_2(
"schedule_prefetch_single_tm", schedule_prefetch_single_tm,
823 fill_scheduled_queues, term_scheduled_dst_events),
824 BENCH_INFO_TM_2(
"schedule_prefetch_burst_tm", schedule_prefetch_burst_tm,
825 fill_scheduled_queues, term_scheduled_dst_events),
829 "Result array is too small to hold all the results");
831static void set_defaults(
void)
833 gbl_args->appl.burst_size = TEST_DEF_BURST;
834 gbl_args->appl.num_queues = 1U;
835 gbl_args->appl.bench_idx = 0U;
836 gbl_args->appl.rounds = TEST_ROUNDS;
837 gbl_args->appl.mode = M_TPUT;
838 gbl_args->appl.is_time =
false;
839 gbl_args->resources.num_buf = TEST_DEF_BURST * TEST_REPEAT_COUNT;
840 gbl_args->resources.buf_size = ODP_CACHE_LINE_SIZE;
846static void print_usage(
char *progname)
849 "OpenDataPlane queue API microbenchmarks.\n"
851 "Usage: %s OPTIONS\n"
854 "Optional OPTIONS:\n"
855 " -b, --burst <num> Test burst size for '*_multi()' functions. Maximum %u.\n"
856 " %u by default. Implementation capabilities may further\n"
857 " limit the value.\n"
858 " -i, --index <idx> Benchmark index to run indefinitely. Index should be\n"
859 " one-based. Use 0 to run all benchmarks. 0 by default.\n"
860 " Registered benchmarks:\n",
861 NO_PATH(progname), NO_PATH(progname), TEST_MAX_BURST, TEST_DEF_BURST);
864 for (uint32_t i = 0U; i < ODPH_ARRAY_SIZE(test_suite); ++i)
865 printf(
" %u: %s\n", i + 1U, test_suite[i].name);
867 printf(
" -r, --rounds <num> Run each test case 'num' times. %u by default.\n"
868 " -t, --time <opt> Time measurement.\n"
869 " 0: measure CPU cycles (default)\n"
871 " -m, --mode <mode> Measurement mode.\n"
872 " 0: measure throughput, track average execution\n"
874 " 1: measure latency, track function minimum and\n"
875 " maximum in addition to average execution time.\n"
876 " -h, --help Display help and exit.\n\n"
880static void check_args(
void)
886 gbl_args->resources.num_buf = TEST_REPEAT_COUNT * gbl_args->appl.burst_size;
888 if (gbl_args->appl.mode != M_TPUT && gbl_args->appl.mode != M_LATENCY) {
889 printf(
"Invalid measurement mode: %d\n", gbl_args->appl.mode);
894 ODPH_ERR(
"Failed to query pool capabilities\n");
898 if (gbl_args->resources.num_buf > p_capa.
buf.
max_num) {
899 ODPH_ERR(
"Invalid amount of buffers: %u (max: %u)\n",
900 gbl_args->resources.num_buf, p_capa.
buf.
max_num);
904 if (gbl_args->resources.buf_size > p_capa.
buf.
max_size)
905 gbl_args->resources.buf_size = p_capa.
buf.
max_size;
908 ODPH_ERR(
"Failed to query queue capabilities\n");
912 if (gbl_args->appl.num_queues * 2U > q_capa.
max_queues) {
913 ODPH_ERR(
"Invalid number of queues: %u (max: %u, any type)\n",
914 gbl_args->appl.num_queues, q_capa.
max_queues);
919 ODPH_ERR(
"Invalid number of queues: %u (max: %u, plain)\n",
920 gbl_args->appl.num_queues, q_capa.
max_queues);
925 ODPH_ERR(
"Invalid queue size: %u (max: %u, plain)\n", gbl_args->resources.num_buf,
931 ODPH_ERR(
"Failed to query schedule capabilities\n");
935 if (gbl_args->appl.num_queues > s_capa.
max_queues) {
936 ODPH_ERR(
"Invalid number of queues: %u (max: %u, scheduled)\n",
937 gbl_args->appl.num_queues, s_capa.
max_queues);
942 ODPH_ERR(
"Invalid queue size: %u (max: %u, scheduled)\n",
948static void parse_args(
int argc,
char *argv[])
951 static const struct option longopts[] = {
952 {
"burst", required_argument, NULL,
'b'},
953 {
"index", required_argument, NULL,
'i'},
954 {
"rounds", required_argument, NULL,
'r'},
955 {
"time", required_argument, NULL,
't'},
956 {
"mode", required_argument, NULL,
'm'},
957 {
"help", no_argument, NULL,
'h'},
960 static const char *shortopts =
"b:i:r:t:m:h";
961 appl_args_t *appl_args = &gbl_args->appl;
964 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
971 appl_args->burst_size = atoi(optarg);
974 appl_args->bench_idx = atoi(optarg);
977 appl_args->rounds = atoi(optarg);
980 appl_args->is_time = atoi(optarg);
983 appl_args->mode = atoi(optarg);
986 print_usage(argv[0]);
1002static int setup_sig_handler(
void)
1004 struct sigaction action;
1006 memset(&action, 0,
sizeof(action));
1007 action.sa_handler = sig_handler;
1011 if (sigemptyset(&action.sa_mask))
1014 if (sigaction(SIGINT, &action, NULL))
1020static int bench_buffer_tm_export(
void *data)
1022 args_t *gbl_args = data;
1023 bench_tm_result_t *res;
1026 const char *unit = gbl_args->appl.is_time ?
"nsec" :
"cpu cycles";
1028 if (test_common_write(
"function name,min %s per function call,"
1029 "average %s per function call,"
1030 "max %s per function call\n", unit, unit, unit)) {
1035 for (uint32_t i = 0; i < gbl_args->suite.s.t.num_bench; i++) {
1036 res = &gbl_args->suite.s.t.result[i];
1038 for (
int j = 0; j < res->num; j++) {
1039 num = res->func[j].num ? res->func[j].num : 1;
1040 if (test_common_write(
"%s,%" PRIu64
",%" PRIu64
",%" PRIu64
"\n",
1042 bench_tm_to_u64(res, &res->func[j].min),
1043 bench_tm_to_u64(res, &res->func[j].tot) / num,
1044 bench_tm_to_u64(res, &res->func[j].max))) {
1052 test_common_write_term();
1057static int bench_buffer_export(
void *data)
1059 args_t *gbl_args = data;
1062 if (test_common_write(
"%s", gbl_args->appl.is_time ?
1063 "function name,average nsec per function call\n" :
1064 "function name,average cpu cycles per function call\n")) {
1069 for (
int i = 0; i < gbl_args->suite.s.b.num_bench; i++) {
1070 if (test_common_write(
"odp_%s,%f\n", gbl_args->suite.s.b.bench[i].desc != NULL ?
1071 gbl_args->suite.s.b.bench[i].desc :
1072 gbl_args->suite.s.b.bench[i].name,
1073 gbl_args->suite.s.b.result[i])) {
1080 test_common_write_term();
1085static void init_suite(args_t *gbl_args)
1087 if (gbl_args->appl.mode == M_LATENCY) {
1088 bench_tm_suite_init(&gbl_args->suite.s.t);
1089 gbl_args->suite.s.t.bench = test_suite_tm;
1090 gbl_args->suite.s.t.num_bench = ODPH_ARRAY_SIZE(test_suite_tm);
1091 gbl_args->suite.s.t.rounds = TEST_REPEAT_COUNT;
1092 gbl_args->suite.s.t.bench_idx = gbl_args->appl.bench_idx;
1093 gbl_args->suite.s.t.measure_time = gbl_args->appl.is_time;
1094 gbl_args->suite.exit = &gbl_args->suite.s.t.exit_worker;
1095 gbl_args->suite.retval = &gbl_args->suite.s.t.retval;
1096 gbl_args->suite.args = &gbl_args->suite.s.t;
1097 gbl_args->suite.suite_fn = bench_tm_run;
1098 gbl_args->suite.export_fn = bench_buffer_tm_export;
1099 gbl_args->suite.s.t.result = gbl_args->suite.r.t;
1101 bench_suite_init(&gbl_args->suite.s.b);
1102 gbl_args->suite.s.b.bench = test_suite;
1103 gbl_args->suite.s.b.num_bench = ODPH_ARRAY_SIZE(test_suite);
1104 gbl_args->suite.s.b.indef_idx = gbl_args->appl.bench_idx;
1105 gbl_args->suite.s.b.rounds = gbl_args->appl.rounds;
1106 gbl_args->suite.s.b.repeat_count = TEST_REPEAT_COUNT;
1107 gbl_args->suite.s.b.measure_time = gbl_args->appl.is_time;
1108 gbl_args->suite.exit = &gbl_args->suite.s.b.exit_worker;
1109 gbl_args->suite.retval = &gbl_args->suite.s.b.retval;
1110 gbl_args->suite.args = &gbl_args->suite.s.b;
1111 gbl_args->suite.suite_fn = bench_run;
1112 gbl_args->suite.export_fn = bench_buffer_export;
1113 gbl_args->suite.s.b.result = gbl_args->suite.r.b;
1117static int create_resources(
void)
1123 ODPH_ERR(
"Failed to configure scheduler\n");
1129 p_param.
buf.
num = gbl_args->resources.num_buf;
1130 p_param.
buf.
size = gbl_args->resources.buf_size;
1134 ODPH_ERR(
"Failed to create test pool\n");
1141 q_param.
context = gbl_args->context;
1142 q_param.
size = gbl_args->resources.num_buf;
1146 ODPH_ERR(
"Failed to create plain test queue\n");
1154 ODPH_ERR(
"Failed to create scheduled test queue\n");
1161static void print_info(
void)
1165 "odp_queue_buffer options\n"
1166 "------------------------\n");
1168 printf(
"Burst size: %d\n", gbl_args->appl.burst_size);
1169 printf(
"CPU mask: %s\n", gbl_args->cpumask_str);
1170 printf(
"Measurement unit: %s\n", gbl_args->appl.is_time ?
"nsec" :
"CPU cycles");
1171 printf(
"Test rounds: %u\n", gbl_args->appl.rounds);
1172 printf(
"Measurement mode: %s\n", gbl_args->appl.mode == M_TPUT ?
"throughput" :
"latency");
1180 odph_thread_t worker_thread;
1181 odph_thread_common_param_t thr_common;
1182 odph_thread_param_t thr_param;
1184 memset(&worker_thread, 0,
sizeof(odph_thread_t));
1187 odph_thread_common_param_init(&thr_common);
1188 thr_common.instance = instance;
1189 thr_common.cpumask = &cpumask;
1190 thr_common.share_param = 1;
1191 odph_thread_param_init(&thr_param);
1192 thr_param.start = gbl_args->suite.suite_fn;
1193 thr_param.arg = gbl_args->suite.args;
1196 if (odph_thread_create(&worker_thread, &thr_common, &thr_param, 1) != 1) {
1197 ODPH_ERR(
"Creating worker thread failed\n");
1201 (void)odph_thread_join(&worker_thread, 1);
1204static void teardown_resources(
void)
1211int main(
int argc,
char *argv[])
1213 odph_helper_options_t helper_options;
1214 test_common_options_t common_options;
1221 argc = odph_parse_options(argc, argv);
1223 if (odph_options(&helper_options)) {
1224 ODPH_ERR(
"Reading ODP helper options failed\n");
1228 argc = test_common_parse_options(argc, argv);
1230 if (test_common_options(&common_options)) {
1231 ODPH_ERR(
"Reading test options failed\n");
1236 init_param.
mem_model = helper_options.mem_model;
1239 ODPH_ERR(
"Global init failed\n");
1244 ODPH_ERR(
"Local init failed\n");
1248 shm =
odp_shm_reserve(
"shm_args",
sizeof(args_t), ODP_CACHE_LINE_SIZE, 0);
1251 ODPH_ERR(
"Shared memory reserve failed\n");
1257 if (gbl_args == NULL) {
1258 ODPH_ERR(
"Shared memory allocation failed\n");
1262 memset(gbl_args, 0,
sizeof(args_t));
1264 parse_args(argc, argv);
1265 init_suite(gbl_args);
1267 if (setup_sig_handler()) {
1268 ODPH_ERR(
"Signal handler setup failed\n");
1273 ODPH_ERR(
"Unable to allocate worker thread\n");
1278 sizeof(gbl_args->cpumask_str));
1280 if (create_resources())
1284 run_worker(instance, default_mask);
1285 ret = *gbl_args->suite.retval;
1287 if (ret == 0 && common_options.is_export) {
1288 if (gbl_args->suite.export_fn(gbl_args)) {
1289 ODPH_ERR(
"Export failed\n");
1294 teardown_resources();
1297 ODPH_ERR(
"Shared memory free failed\n");
1302 ODPH_ERR(
"Local term local\n");
1307 ODPH_ERR(
"Global term global\n");
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable.
odp_event_t odp_buffer_to_event(odp_buffer_t buf)
Convert buffer handle to event.
odp_buffer_t odp_buffer_alloc(odp_pool_t pool)
Buffer alloc.
#define ODP_BUFFER_INVALID
Invalid buffer.
#define ODP_UNUSED
Intentionally unused variables of functions.
void odp_cpumask_set(odp_cpumask_t *mask, int cpu)
Add CPU to mask.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
int odp_cpumask_first(const odp_cpumask_t *mask)
Find first set CPU in mask.
void odp_cpumask_zero(odp_cpumask_t *mask)
Clear entire CPU mask.
int32_t odp_cpumask_to_str(const odp_cpumask_t *mask, char *str, int32_t size)
Format a string from CPU mask.
#define ODP_CPUMASK_STR_SIZE
The maximum number of characters needed to record any CPU mask as a string (output of odp_cpumask_to_...
void odp_event_free(odp_event_t event)
Free event.
#define ODP_EVENT_INVALID
Invalid event.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
#define ODP_STATIC_ASSERT(cond, msg)
Compile time assertion macro.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
int odp_pool_capability(odp_pool_capability_t *capa)
Query pool capabilities.
void odp_pool_param_init(odp_pool_param_t *param)
Initialize pool params.
int odp_pool_destroy(odp_pool_t pool)
Destroy a pool previously created by odp_pool_create()
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_BUFFER
Buffer pool.
void * odp_queue_context(odp_queue_t queue)
Get queue context.
int odp_queue_context_set(odp_queue_t queue, void *context, uint32_t len)
Set queue context.
int odp_queue_enq_multi(odp_queue_t queue, const odp_event_t events[], int num)
Enqueue multiple events to a queue.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
int odp_queue_capability(odp_queue_capability_t *capa)
Query queue capabilities.
#define ODP_QUEUE_INVALID
Invalid queue.
odp_event_t odp_queue_deq(odp_queue_t queue)
Dequeue an event from a queue.
int odp_queue_enq(odp_queue_t queue, odp_event_t ev)
Enqueue an event to a queue.
odp_queue_t odp_queue_create(const char *name, const odp_queue_param_t *param)
Queue create.
int odp_queue_destroy(odp_queue_t queue)
Destroy ODP queue.
int odp_queue_deq_multi(odp_queue_t queue, odp_event_t events[], int num)
Dequeue multiple events from a queue.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
@ ODP_QUEUE_OP_MT_UNSAFE
Not multithread safe operation.
int odp_schedule_multi_no_wait(odp_queue_t *from, odp_event_t events[], int num)
Schedule, do not wait for events.
int odp_schedule_multi(odp_queue_t *from, uint64_t wait, odp_event_t events[], int num)
Schedule multiple events.
#define ODP_SCHED_NO_WAIT
Do not wait.
void odp_schedule_prefetch(int num)
Prefetch events for next schedule call.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
int odp_schedule_multi_wait(odp_queue_t *from, odp_event_t events[], int num)
Schedule, wait for events.
uint64_t odp_schedule_wait_time(uint64_t ns)
Schedule wait time.
int odp_schedule_capability(odp_schedule_capability_t *capa)
Query scheduler capabilities.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
#define ODP_SHM_INVALID
Invalid shared memory block.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
bool odp_bool_t
Boolean type.
void odp_sys_info_print(void)
Print system info.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
#define ODP_TIME_MSEC_IN_NS
A millisecond in nanoseconds.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
uint32_t max_num
Maximum number of buffers of any size.
struct odp_pool_capability_t::@133 buf
Buffer pool capabilities
uint32_t max_size
Maximum buffer data size in bytes.
uint32_t num
Number of buffers in the pool.
uint32_t size
Minimum buffer size in bytes.
odp_pool_type_t type
Pool type.
struct odp_pool_param_t::@138 buf
Parameters for buffer pools.
struct odp_queue_capability_t::@155 plain
Plain queue capabilities.
uint32_t max_size
Maximum number of events a plain (ODP_BLOCKING) queue can store simultaneously.
uint32_t max_num
Maximum number of plain (ODP_BLOCKING) queues of the default size.
uint32_t max_queues
Maximum number of event queues of any type (default size).
odp_queue_op_mode_t enq_mode
Enqueue mode.
odp_queue_type_t type
Queue type.
void * context
Queue context pointer.
odp_queue_op_mode_t deq_mode
Dequeue mode.
uint32_t max_queues
Maximum number of scheduled (ODP_BLOCKING) queues of the default size.
uint32_t max_queue_size
Maximum number of events a scheduled (ODP_BLOCKING) queue can store simultaneously.