1 /* SPDX-License-Identifier: BSD-3-Clause 2 */ 3 4 #include "spdk/stdinc.h" 5 6 #include "spdk/env.h" 7 #include "spdk/event.h" 8 #include "spdk/string.h" 9 #include "spdk/thread.h" 10 #include "spdk/util.h" 11 12 #define MAX_NUM_POLLERS 1000 13 14 static int g_time_in_sec; 15 static int g_period_in_usec; 16 static int g_num_pollers; 17 18 static struct spdk_poller *g_timer; 19 static struct spdk_poller *g_pollers[MAX_NUM_POLLERS]; 20 static uint64_t g_run_count; 21 22 static struct spdk_thread_stats g_start_stats; 23 24 static int 25 poller_run(void *arg) 26 { 27 g_run_count++; 28 29 return SPDK_POLLER_BUSY; 30 } 31 32 static void 33 _poller_perf_end(void) 34 { 35 struct spdk_thread_stats end_stats; 36 uint64_t tsc_hz, busy_cyc, poller_cost_cyc, poller_cost_nsec; 37 int i; 38 39 spdk_thread_get_stats(&end_stats); 40 busy_cyc = end_stats.busy_tsc - g_start_stats.busy_tsc; 41 42 tsc_hz = spdk_get_ticks_hz(); 43 44 printf("\r ======================================\n"); 45 46 printf("\r busy:%" PRIu64 " (cyc)\n", busy_cyc); 47 printf("\r total_run_count: %" PRIu64 "\n", g_run_count); 48 printf("\r tsc_hz: %" PRIu64 " (cyc)\n", tsc_hz); 49 50 printf("\r ======================================\n"); 51 52 poller_cost_cyc = busy_cyc / g_run_count; 53 poller_cost_nsec = (poller_cost_cyc * SPDK_SEC_TO_NSEC) / tsc_hz; 54 55 printf("\r poller_cost: %" PRIu64 " (cyc), %" PRIu64 " (nsec)\n", 56 poller_cost_cyc, poller_cost_nsec); 57 58 spdk_poller_unregister(&g_timer); 59 60 for (i = 0; i < g_num_pollers; i++) { 61 spdk_poller_unregister(&g_pollers[i]); 62 } 63 64 spdk_app_stop(0); 65 } 66 67 static int 68 poller_perf_end(void *arg) 69 { 70 _poller_perf_end(); 71 72 return SPDK_POLLER_BUSY; 73 } 74 75 static void 76 poller_perf_start(void *arg1) 77 { 78 int i; 79 80 printf("Running %d pollers for %d seconds with %d microseconds period.\n", 81 g_num_pollers, g_time_in_sec, g_period_in_usec); 82 fflush(stdout); 83 84 for (i = 0; i < g_num_pollers; i++) { 85 g_pollers[i] = SPDK_POLLER_REGISTER(poller_run, NULL, g_period_in_usec); 86 } 87 88 spdk_thread_get_stats(&g_start_stats); 89 90 g_timer = SPDK_POLLER_REGISTER(poller_perf_end, NULL, g_time_in_sec * SPDK_SEC_TO_USEC); 91 } 92 93 static void 94 poller_perf_shutdown_cb(void) 95 { 96 _poller_perf_end(); 97 } 98 99 static int 100 poller_perf_parse_arg(int ch, char *arg) 101 { 102 int tmp; 103 104 tmp = spdk_strtol(optarg, 10); 105 if (tmp < 0) { 106 fprintf(stderr, "Parse failed for the option %c.\n", ch); 107 return tmp; 108 } 109 110 switch (ch) { 111 case 'b': 112 g_num_pollers = tmp; 113 break; 114 case 'l': 115 g_period_in_usec = tmp; 116 break; 117 case 't': 118 g_time_in_sec = tmp; 119 break; 120 default: 121 return -EINVAL; 122 } 123 124 return 0; 125 } 126 127 static void 128 poller_perf_usage(void) 129 { 130 printf(" -b <number> number of pollers\n"); 131 printf(" -l <period> poller period in usec\n"); 132 printf(" -t <time> run time in seconds\n"); 133 } 134 135 static int 136 poller_perf_verify_params(void) 137 { 138 if (g_num_pollers <= 0 || g_num_pollers > MAX_NUM_POLLERS) { 139 fprintf(stderr, "number of pollers must not be more than %d\n", MAX_NUM_POLLERS); 140 return -EINVAL; 141 } 142 143 if (g_period_in_usec < 0) { 144 fprintf(stderr, "period of poller cannot be negative\n"); 145 return -EINVAL; 146 } 147 148 if (g_time_in_sec <= 0) { 149 fprintf(stderr, "run time must be positive\n"); 150 return -EINVAL; 151 } 152 153 return 0; 154 } 155 156 int 157 main(int argc, char **argv) 158 { 159 struct spdk_app_opts opts; 160 int rc; 161 162 spdk_app_opts_init(&opts, sizeof(opts)); 163 opts.name = "poller_perf"; 164 opts.shutdown_cb = poller_perf_shutdown_cb; 165 opts.rpc_addr = NULL; 166 167 rc = spdk_app_parse_args(argc, argv, &opts, "b:l:t:", NULL, 168 poller_perf_parse_arg, poller_perf_usage); 169 if (rc != SPDK_APP_PARSE_ARGS_SUCCESS) { 170 return rc; 171 } 172 173 rc = poller_perf_verify_params(); 174 if (rc != 0) { 175 return rc; 176 } 177 178 rc = spdk_app_start(&opts, poller_perf_start, NULL); 179 180 spdk_app_fini(); 181 182 return rc; 183 } 184