]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/test-bus-benchmark.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-benchmark.c
CommitLineData
8f155917
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
8f155917
LP
22#include <sys/wait.h>
23
8f155917 24#include "sd-bus.h"
07630cea 25
8f155917 26#include "bus-internal.h"
07630cea 27#include "bus-kernel.h"
057171ef 28#include "bus-util.h"
07630cea
LP
29#include "def.h"
30#include "time-util.h"
31#include "util.h"
8f155917 32
1679ddc4 33#define MAX_SIZE (2*1024*1024)
8f155917 34
59967d30 35static usec_t arg_loop_usec = 100 * USEC_PER_MSEC;
061b2c43 36
77cfd113
TG
37typedef enum Type {
38 TYPE_KDBUS,
39 TYPE_LEGACY,
40 TYPE_DIRECT,
41} Type;
42
832d16a6 43static void server(sd_bus *b, size_t *result) {
8f155917
LP
44 int r;
45
46 for (;;) {
47 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
48
49 r = sd_bus_process(b, &m);
50 assert_se(r >= 0);
51
52 if (r == 0)
3a43da28 53 assert_se(sd_bus_wait(b, USEC_INFINITY) >= 0);
8f155917
LP
54 if (!m)
55 continue;
56
832d16a6 57 if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping"))
df2d202e 58 assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
832d16a6
LP
59 else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) {
60 const void *p;
61 size_t sz;
8f155917 62
832d16a6
LP
63 /* Make sure the mmap is mapped */
64 assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0);
8f155917 65
def3f524
DM
66 r = sd_bus_reply_method_return(m, NULL);
67 assert_se(r >= 0);
8f155917 68 } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) {
832d16a6
LP
69 uint64_t res;
70 assert_se(sd_bus_message_read(m, "t", &res) > 0);
8f155917 71
832d16a6 72 *result = res;
8f155917
LP
73 return;
74
77cfd113 75 } else if (!sd_bus_message_is_signal(m, NULL, NULL))
8f155917
LP
76 assert_not_reached("Unknown method");
77 }
78}
79
def3f524 80static void transaction(sd_bus *b, size_t sz, const char *server_name) {
8f155917 81 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
832d16a6 82 uint8_t *p;
8f155917 83
def3f524 84 assert_se(sd_bus_message_new_method_call(b, &m, server_name, "/", "benchmark.server", "Work") >= 0);
8f155917
LP
85 assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0);
86
31175451 87 memset(p, 0x80, sz);
8f155917 88
c49b30a2 89 assert_se(sd_bus_call(b, m, 0, NULL, &reply) >= 0);
832d16a6
LP
90}
91
def3f524 92static void client_bisect(const char *address, const char *server_name) {
832d16a6
LP
93 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
94 size_t lsize, rsize, csize;
95 sd_bus *b;
96 int r;
97
98 r = sd_bus_new(&b);
99 assert_se(r >= 0);
100
101 r = sd_bus_set_address(b, address);
102 assert_se(r >= 0);
103
104 r = sd_bus_start(b);
105 assert_se(r >= 0);
106
def3f524
DM
107 r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL);
108 assert_se(r >= 0);
832d16a6
LP
109
110 lsize = 1;
111 rsize = MAX_SIZE;
112
31175451
KS
113 printf("SIZE\tCOPY\tMEMFD\n");
114
832d16a6 115 for (;;) {
061b2c43
LP
116 usec_t t;
117 unsigned n_copying, n_memfd;
832d16a6
LP
118
119 csize = (lsize + rsize) / 2;
120
832d16a6
LP
121 if (csize <= lsize)
122 break;
123
124 if (csize <= 0)
125 break;
8f155917 126
83d97ce6 127 printf("%zu\t", csize);
31175451 128
832d16a6 129 b->use_memfd = 0;
061b2c43 130
832d16a6 131 t = now(CLOCK_MONOTONIC);
061b2c43 132 for (n_copying = 0;; n_copying++) {
def3f524 133 transaction(b, csize, server_name);
061b2c43
LP
134 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
135 break;
136 }
31175451 137 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
061b2c43 138
832d16a6 139 b->use_memfd = -1;
061b2c43 140
832d16a6 141 t = now(CLOCK_MONOTONIC);
061b2c43 142 for (n_memfd = 0;; n_memfd++) {
def3f524 143 transaction(b, csize, server_name);
061b2c43
LP
144 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
145 break;
146 }
6cbf6931 147 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
061b2c43
LP
148
149 if (n_copying == n_memfd)
832d16a6
LP
150 break;
151
061b2c43 152 if (n_copying > n_memfd)
832d16a6
LP
153 lsize = csize;
154 else
155 rsize = csize;
8f155917
LP
156 }
157
31175451 158 b->use_memfd = 1;
def3f524 159 assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0);
31175451
KS
160 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
161 assert_se(sd_bus_send(b, x, NULL) >= 0);
162
163 sd_bus_unref(b);
164}
165
77cfd113 166static void client_chart(Type type, const char *address, const char *server_name, int fd) {
31175451
KS
167 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
168 size_t csize;
169 sd_bus *b;
170 int r;
171
172 r = sd_bus_new(&b);
173 assert_se(r >= 0);
174
77cfd113
TG
175 if (type == TYPE_DIRECT) {
176 r = sd_bus_set_fd(b, fd, fd);
177 assert_se(r >= 0);
178 } else {
179 r = sd_bus_set_address(b, address);
180 assert_se(r >= 0);
181
182 r = sd_bus_set_bus_client(b, true);
183 assert_se(r >= 0);
184 }
31175451
KS
185
186 r = sd_bus_start(b);
187 assert_se(r >= 0);
188
77cfd113
TG
189 r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL);
190 assert_se(r >= 0);
31175451 191
77cfd113
TG
192 switch (type) {
193 case TYPE_KDBUS:
194 printf("SIZE\tCOPY\tMEMFD\n");
195 break;
196 case TYPE_LEGACY:
197 printf("SIZE\tLEGACY\n");
198 break;
199 case TYPE_DIRECT:
200 printf("SIZE\tDIRECT\n");
201 break;
202 }
31175451 203
83d97ce6 204 for (csize = 1; csize <= MAX_SIZE; csize *= 2) {
31175451
KS
205 usec_t t;
206 unsigned n_copying, n_memfd;
207
83d97ce6 208 printf("%zu\t", csize);
31175451 209
77cfd113
TG
210 if (type == TYPE_KDBUS) {
211 b->use_memfd = 0;
31175451 212
77cfd113
TG
213 t = now(CLOCK_MONOTONIC);
214 for (n_copying = 0;; n_copying++) {
215 transaction(b, csize, server_name);
216 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
217 break;
218 }
31175451 219
77cfd113 220 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
31175451 221
77cfd113
TG
222 b->use_memfd = -1;
223 }
31175451
KS
224
225 t = now(CLOCK_MONOTONIC);
226 for (n_memfd = 0;; n_memfd++) {
def3f524 227 transaction(b, csize, server_name);
31175451
KS
228 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
229 break;
230 }
231
232 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
233 }
234
235 b->use_memfd = 1;
def3f524 236 assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0);
832d16a6
LP
237 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
238 assert_se(sd_bus_send(b, x, NULL) >= 0);
8f155917 239
832d16a6 240 sd_bus_unref(b);
8f155917
LP
241}
242
832d16a6 243int main(int argc, char *argv[]) {
31175451
KS
244 enum {
245 MODE_BISECT,
246 MODE_CHART,
247 } mode = MODE_BISECT;
77cfd113
TG
248 Type type = TYPE_KDBUS;
249 int i, pair[2] = { -1, -1 };
def3f524 250 _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *server_name = NULL;
832d16a6 251 _cleanup_close_ int bus_ref = -1;
def3f524 252 const char *unique;
832d16a6
LP
253 cpu_set_t cpuset;
254 size_t result;
8f155917 255 sd_bus *b;
8f155917 256 pid_t pid;
832d16a6
LP
257 int r;
258
31175451
KS
259 for (i = 1; i < argc; i++) {
260 if (streq(argv[i], "chart")) {
261 mode = MODE_CHART;
262 continue;
77cfd113
TG
263 } else if (streq(argv[i], "legacy")) {
264 type = TYPE_LEGACY;
265 continue;
266 } else if (streq(argv[i], "direct")) {
267 type = TYPE_DIRECT;
268 continue;
31175451
KS
269 }
270
271 assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
272 }
061b2c43 273
77cfd113
TG
274 assert_se(!MODE_BISECT || TYPE_KDBUS);
275
061b2c43
LP
276 assert_se(arg_loop_usec > 0);
277
77cfd113
TG
278 if (type == TYPE_KDBUS) {
279 assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
280
281 bus_ref = bus_kernel_create_bus(name, false, &bus_name);
282 if (bus_ref == -ENOENT)
283 exit(EXIT_TEST_SKIP);
79ccff06 284
77cfd113 285 assert_se(bus_ref >= 0);
8f155917 286
77cfd113
TG
287 address = strappend("kernel:path=", bus_name);
288 assert_se(address);
289 } else if (type == TYPE_LEGACY) {
290 const char *e;
8f155917 291
77cfd113
TG
292 e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
293 assert_se(e);
294
295 address = strdup(e);
296 assert_se(address);
297 }
8f155917
LP
298
299 r = sd_bus_new(&b);
300 assert_se(r >= 0);
301
77cfd113
TG
302 if (type == TYPE_DIRECT) {
303 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0);
304
305 r = sd_bus_set_fd(b, pair[0], pair[0]);
306 assert_se(r >= 0);
307
308 r = sd_bus_set_server(b, true, SD_ID128_NULL);
309 assert_se(r >= 0);
310 } else {
311 r = sd_bus_set_address(b, address);
312 assert_se(r >= 0);
313
314 r = sd_bus_set_bus_client(b, true);
315 assert_se(r >= 0);
316 }
8f155917
LP
317
318 r = sd_bus_start(b);
319 assert_se(r >= 0);
320
77cfd113
TG
321 if (type != TYPE_DIRECT) {
322 r = sd_bus_get_unique_name(b, &unique);
323 assert_se(r >= 0);
def3f524 324
77cfd113
TG
325 server_name = strdup(unique);
326 assert_se(server_name);
327 }
def3f524 328
832d16a6
LP
329 sync();
330 setpriority(PRIO_PROCESS, 0, -19);
331
8f155917
LP
332 pid = fork();
333 assert_se(pid >= 0);
334
335 if (pid == 0) {
832d16a6
LP
336 CPU_ZERO(&cpuset);
337 CPU_SET(0, &cpuset);
338 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
339
03e334a1 340 safe_close(bus_ref);
8f155917
LP
341 sd_bus_unref(b);
342
31175451
KS
343 switch (mode) {
344 case MODE_BISECT:
def3f524 345 client_bisect(address, server_name);
31175451
KS
346 break;
347
348 case MODE_CHART:
77cfd113 349 client_chart(type, address, server_name, pair[1]);
31175451
KS
350 break;
351 }
352
8f155917
LP
353 _exit(0);
354 }
355
832d16a6
LP
356 CPU_ZERO(&cpuset);
357 CPU_SET(1, &cpuset);
358 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
8f155917 359
832d16a6 360 server(b, &result);
8f155917 361
31175451
KS
362 if (mode == MODE_BISECT)
363 printf("Copying/memfd are equally fast at %zu bytes\n", result);
8f155917 364
832d16a6 365 assert_se(waitpid(pid, NULL, 0) == pid);
8f155917 366
77cfd113 367 safe_close(pair[1]);
832d16a6 368 sd_bus_unref(b);
8f155917
LP
369
370 return 0;
371}