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