aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/perf_mq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/perf_mq.c')
-rw-r--r--src/lib/util/perf_mq.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/src/lib/util/perf_mq.c b/src/lib/util/perf_mq.c
new file mode 100644
index 000000000..5c956e4e9
--- /dev/null
+++ b/src/lib/util/perf_mq.c
@@ -0,0 +1,301 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2018, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/perf_mq.c
23 * @brief benchmark for mq
24 * @author Florian Dold
25 * @author Christian Grothoff
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include <gauger.h>
31
32#define NUM_TRANSMISSIONS 1000000
33
34/**
35 * How long does the receiver take per message?
36 */
37#define RECEIVER_THROTTLE GNUNET_TIME_relative_multiply ( \
38 GNUNET_TIME_UNIT_MILLISECONDS, 1)
39
40static unsigned int received_cnt;
41
42
43GNUNET_NETWORK_STRUCT_BEGIN
44
45struct MyMessage
46{
47 struct GNUNET_MessageHeader header;
48 uint32_t x GNUNET_PACKED;
49};
50
51GNUNET_NETWORK_STRUCT_END
52
53static int global_ret;
54
55static struct GNUNET_SCHEDULER_Task *task;
56
57static struct GNUNET_MQ_Handle *cmq;
58
59
60static void
61do_shutdown (void *cls)
62{
63 (void) cls;
64 if (NULL != task)
65 {
66 GNUNET_SCHEDULER_cancel (task);
67 task = NULL;
68 }
69 if (NULL != cmq)
70 {
71 GNUNET_MQ_destroy (cmq);
72 cmq = NULL;
73 }
74}
75
76
77/**
78 * Generic error handler, called with the appropriate
79 * error code and the same closure specified at the creation of
80 * the message queue.
81 * Not every message queue implementation supports an error handler.
82 *
83 * @param cls closure
84 * @param error error code
85 */
86static void
87error_cb (void *cls,
88 enum GNUNET_MQ_Error error)
89{
90 GNUNET_break (0);
91 global_ret = 3;
92 GNUNET_SCHEDULER_shutdown ();
93}
94
95
96static void
97handle_dummy (void *cls,
98 const struct MyMessage *msg)
99{
100 struct GNUNET_SERVICE_Client *c = cls;
101
102 GNUNET_SERVICE_client_continue (c);
103 if (received_cnt != ntohl (msg->x))
104 {
105 GNUNET_break (0);
106 global_ret = 4;
107 GNUNET_SCHEDULER_shutdown ();
108 }
109 received_cnt++;
110}
111
112
113static void
114handle_dummy2 (void *cls,
115 const struct MyMessage *msg)
116{
117 struct GNUNET_SERVICE_Client *c = cls;
118
119 GNUNET_SERVICE_client_continue (c);
120 if (NUM_TRANSMISSIONS != received_cnt)
121 {
122 GNUNET_break (0);
123 global_ret = 5;
124 }
125 GNUNET_SCHEDULER_shutdown ();
126}
127
128
129static void
130do_send (void *cls);
131
132
133/**
134 * Function called whenever MQ has sent a message.
135 */
136static void
137notify_sent_cb (void *cls)
138{
139 static unsigned int seen;
140 unsigned int *cnt = cls;
141
142 if (seen != *cnt)
143 {
144 GNUNET_break (0);
145 global_ret = 6;
146 GNUNET_SCHEDULER_shutdown ();
147 }
148 seen++;
149 GNUNET_free (cnt);
150 task = GNUNET_SCHEDULER_add_now (&do_send,
151 NULL);
152}
153
154
155static void
156do_send (void *cls)
157{
158 static unsigned int i = 0;
159 unsigned int *cnt;
160 struct GNUNET_MQ_Envelope *env;
161 struct MyMessage *m;
162
163 task = NULL;
164 if (NUM_TRANSMISSIONS == i)
165 {
166 env = GNUNET_MQ_msg (m,
167 GNUNET_MESSAGE_TYPE_DUMMY2);
168 GNUNET_MQ_send (cmq,
169 env);
170 return;
171 }
172 cnt = GNUNET_new (unsigned int);
173 *cnt = i;
174 env = GNUNET_MQ_msg (m,
175 GNUNET_MESSAGE_TYPE_DUMMY);
176 GNUNET_MQ_notify_sent (env,
177 &notify_sent_cb,
178 cnt);
179 m->x = htonl (i);
180 GNUNET_MQ_send (cmq,
181 env);
182 i++;
183}
184
185
186/**
187 * Start running the actual test.
188 *
189 * @param cls closure passed to #GNUNET_SERVICE_MAIN
190 * @param cfg configuration to use for this service
191 * @param sh handle to the newly create service
192 */
193static void
194run (void *cls,
195 const struct GNUNET_CONFIGURATION_Handle *cfg,
196 struct GNUNET_SERVICE_Handle *sh)
197{
198 struct GNUNET_MQ_MessageHandler ch[] = {
199 GNUNET_MQ_handler_end ()
200 };
201
202 (void) cls;
203 (void) sh;
204 cmq = GNUNET_CLIENT_connect (cfg,
205 "test_client",
206 ch,
207 &error_cb,
208 NULL);
209 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
210 NULL);
211 task = GNUNET_SCHEDULER_add_now (&do_send,
212 NULL);
213}
214
215
216/**
217 * Callback to be called when a client connects to the service.
218 *
219 * @param cls closure for the service
220 * @param c the new client that connected to the service
221 * @param mq the message queue used to send messages to the client
222 * @return the client-specific (`internal') closure
223 */
224static void *
225connect_cb (void *cls,
226 struct GNUNET_SERVICE_Client *c,
227 struct GNUNET_MQ_Handle *mq)
228{
229 (void) cls;
230 (void) mq;
231 return c;
232}
233
234
235/**
236 * Callback to be called when a client disconnected from the service
237 *
238 * @param cls closure for the service
239 * @param c the client that disconnected
240 * @param internal_cls the client-specific (`internal') closure
241 */
242static void
243disconnect_cb (void *cls,
244 struct GNUNET_SERVICE_Client *c,
245 void *internal_cls)
246{
247 (void) cls;
248 (void) c;
249 (void) internal_cls;
250}
251
252
253int
254main (int argc, char **argv)
255{
256 struct GNUNET_TIME_Absolute start;
257 char *test_argv[] = {
258 (char *) "test_client",
259 "-c",
260 "test_client_data.conf",
261 NULL
262 };
263 struct GNUNET_MQ_MessageHandler mh[] = {
264 GNUNET_MQ_hd_fixed_size (dummy,
265 GNUNET_MESSAGE_TYPE_DUMMY,
266 struct MyMessage,
267 NULL),
268 GNUNET_MQ_hd_fixed_size (dummy2,
269 GNUNET_MESSAGE_TYPE_DUMMY2,
270 struct MyMessage,
271 NULL),
272 GNUNET_MQ_handler_end ()
273 };
274
275 (void) argc;
276 (void) argv;
277 GNUNET_log_setup ("perf-mq",
278 "INFO",
279 NULL);
280 start = GNUNET_TIME_absolute_get ();
281 if (0 !=
282 GNUNET_SERVICE_run_ (3,
283 test_argv,
284 "test_client",
285 GNUNET_SERVICE_OPTION_NONE,
286 &run,
287 &connect_cb,
288 &disconnect_cb,
289 NULL,
290 mh))
291 return 1;
292 printf ("Scheduler perf took %s\n",
293 GNUNET_STRINGS_relative_time_to_string (
294 GNUNET_TIME_absolute_get_duration (start),
295 GNUNET_YES));
296 GAUGER ("UTIL", "Scheduler",
297 received_cnt / 1024 / (1
298 + GNUNET_TIME_absolute_get_duration
299 (start).rel_value_us / 1000LL), "kmsg/ms");
300 return global_ret;
301}