xref: /spdk/test/thread/poller_perf/poller_perf.c (revision 877573897ad52be4fa8989f7617bd655b87e05c4)
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 
166 	rc = spdk_app_parse_args(argc, argv, &opts, "b:l:t:", NULL,
167 				 poller_perf_parse_arg, poller_perf_usage);
168 	if (rc != SPDK_APP_PARSE_ARGS_SUCCESS) {
169 		return rc;
170 	}
171 
172 	rc = poller_perf_verify_params();
173 	if (rc != 0) {
174 		return rc;
175 	}
176 
177 	rc = spdk_app_start(&opts, poller_perf_start, NULL);
178 
179 	spdk_app_fini();
180 
181 	return rc;
182 }
183