1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk/env.h" 37 #include "spdk/event.h" 38 #include "spdk/string.h" 39 #include "spdk/thread.h" 40 #include "spdk/util.h" 41 42 #define MAX_NUM_POLLERS 1000 43 44 static int g_time_in_sec; 45 static int g_period_in_usec; 46 static int g_num_pollers; 47 48 static struct spdk_poller *g_timer; 49 static struct spdk_poller *g_pollers[MAX_NUM_POLLERS]; 50 static uint64_t g_run_count; 51 52 static struct spdk_thread_stats g_start_stats; 53 54 static int 55 poller_run(void *arg) 56 { 57 g_run_count++; 58 59 return SPDK_POLLER_BUSY; 60 } 61 62 static void 63 _poller_perf_end(void) 64 { 65 struct spdk_thread_stats end_stats; 66 uint64_t tsc_hz, busy_cyc, poller_cost_cyc, poller_cost_nsec; 67 int i; 68 69 spdk_thread_get_stats(&end_stats); 70 busy_cyc = end_stats.busy_tsc - g_start_stats.busy_tsc; 71 72 tsc_hz = spdk_get_ticks_hz(); 73 74 printf("\r ======================================\n"); 75 76 printf("\r busy:%" PRIu64 " (cyc)\n", busy_cyc); 77 printf("\r total_run_count: %" PRIu64 "\n", g_run_count); 78 printf("\r tsc_hz: %" PRIu64 " (cyc)\n", tsc_hz); 79 80 printf("\r ======================================\n"); 81 82 poller_cost_cyc = busy_cyc / g_run_count; 83 poller_cost_nsec = (poller_cost_cyc * SPDK_SEC_TO_NSEC) / tsc_hz; 84 85 printf("\r poller_cost: %" PRIu64 " (cyc), %" PRIu64 " (nsec)\n", 86 poller_cost_cyc, poller_cost_nsec); 87 88 spdk_poller_unregister(&g_timer); 89 90 for (i = 0; i < g_num_pollers; i++) { 91 spdk_poller_unregister(&g_pollers[i]); 92 } 93 94 spdk_app_stop(0); 95 } 96 97 static int 98 poller_perf_end(void *arg) 99 { 100 _poller_perf_end(); 101 102 return SPDK_POLLER_BUSY; 103 } 104 105 static void 106 poller_perf_start(void *arg1) 107 { 108 int i; 109 110 printf("Running %d pollers for %d seconds with %d microseconds period.\n", 111 g_num_pollers, g_time_in_sec, g_period_in_usec); 112 fflush(stdout); 113 114 for (i = 0; i < g_num_pollers; i++) { 115 g_pollers[i] = SPDK_POLLER_REGISTER(poller_run, NULL, g_period_in_usec); 116 } 117 118 spdk_thread_get_stats(&g_start_stats); 119 120 g_timer = SPDK_POLLER_REGISTER(poller_perf_end, NULL, g_time_in_sec * SPDK_SEC_TO_USEC); 121 } 122 123 static void 124 poller_perf_shutdown_cb(void) 125 { 126 _poller_perf_end(); 127 } 128 129 static int 130 poller_perf_parse_arg(int ch, char *arg) 131 { 132 int tmp; 133 134 tmp = spdk_strtol(optarg, 10); 135 if (tmp < 0) { 136 fprintf(stderr, "Parse failed for the option %c.\n", ch); 137 return tmp; 138 } 139 140 switch (ch) { 141 case 'b': 142 g_num_pollers = tmp; 143 break; 144 case 'l': 145 g_period_in_usec = tmp; 146 break; 147 case 't': 148 g_time_in_sec = tmp; 149 break; 150 default: 151 return -EINVAL; 152 } 153 154 return 0; 155 } 156 157 static void 158 poller_perf_usage(void) 159 { 160 printf(" -b <number> number of pollers\n"); 161 printf(" -l <period> poller period in usec\n"); 162 printf(" -t <time> run time in seconds\n"); 163 } 164 165 static int 166 poller_perf_verify_params(void) 167 { 168 if (g_num_pollers <= 0 || g_num_pollers > MAX_NUM_POLLERS) { 169 fprintf(stderr, "number of pollers must not be more than %d\n", MAX_NUM_POLLERS); 170 return -EINVAL; 171 } 172 173 if (g_period_in_usec < 0) { 174 fprintf(stderr, "period of poller cannot be negative\n"); 175 return -EINVAL; 176 } 177 178 if (g_time_in_sec <= 0) { 179 fprintf(stderr, "run time must be positive\n"); 180 return -EINVAL; 181 } 182 183 return 0; 184 } 185 186 int 187 main(int argc, char **argv) 188 { 189 struct spdk_app_opts opts; 190 int rc; 191 192 spdk_app_opts_init(&opts, sizeof(opts)); 193 opts.name = "poller_perf"; 194 opts.shutdown_cb = poller_perf_shutdown_cb; 195 196 rc = spdk_app_parse_args(argc, argv, &opts, "b:l:t:", NULL, 197 poller_perf_parse_arg, poller_perf_usage); 198 if (rc != SPDK_APP_PARSE_ARGS_SUCCESS) { 199 return rc; 200 } 201 202 rc = poller_perf_verify_params(); 203 if (rc != 0) { 204 return rc; 205 } 206 207 rc = spdk_app_start(&opts, poller_perf_start, NULL); 208 209 spdk_app_fini(); 210 211 return rc; 212 } 213