]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/test-bus-kernel-benchmark.c
bus: rename sd_bus_send_with_reply_and_block() to sd_bus_call()
[thirdparty/systemd.git] / src / libsystemd-bus / test-bus-kernel-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
22#include <ctype.h>
23#include <sys/wait.h>
24
25#include "util.h"
26#include "log.h"
061b2c43 27#include "time-util.h"
8f155917
LP
28
29#include "sd-bus.h"
30#include "bus-message.h"
31#include "bus-error.h"
32#include "bus-kernel.h"
33#include "bus-internal.h"
40ca29a1 34#include "bus-util.h"
8f155917 35
83d97ce6 36#define MAX_SIZE (4*1024*1024)
8f155917 37
59967d30 38static usec_t arg_loop_usec = 100 * USEC_PER_MSEC;
061b2c43 39
832d16a6 40static void server(sd_bus *b, size_t *result) {
8f155917
LP
41 int r;
42
43 for (;;) {
44 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
45
46 r = sd_bus_process(b, &m);
47 assert_se(r >= 0);
48
49 if (r == 0)
50 assert_se(sd_bus_wait(b, (usec_t) -1) >= 0);
8f155917
LP
51 if (!m)
52 continue;
53
832d16a6
LP
54 if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping"))
55 assert_se(sd_bus_reply_method_return(b, m, NULL) >= 0);
56 else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) {
57 const void *p;
58 size_t sz;
8f155917 59
832d16a6
LP
60 /* Make sure the mmap is mapped */
61 assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0);
8f155917 62
832d16a6 63 assert_se(sd_bus_reply_method_return(b, m, NULL) >= 0);
8f155917 64 } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) {
832d16a6
LP
65 uint64_t res;
66 assert_se(sd_bus_message_read(m, "t", &res) > 0);
8f155917 67
832d16a6 68 *result = res;
8f155917
LP
69 return;
70
8f155917
LP
71 } else
72 assert_not_reached("Unknown method");
73 }
74}
75
832d16a6 76static void transaction(sd_bus *b, size_t sz) {
8f155917 77 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
832d16a6 78 uint8_t *p;
8f155917
LP
79
80 assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Work", &m) >= 0);
81 assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0);
82
31175451 83 memset(p, 0x80, sz);
8f155917 84
c49b30a2 85 assert_se(sd_bus_call(b, m, 0, NULL, &reply) >= 0);
832d16a6
LP
86}
87
31175451 88static void client_bisect(const char *address) {
832d16a6
LP
89 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
90 size_t lsize, rsize, csize;
91 sd_bus *b;
92 int r;
93
94 r = sd_bus_new(&b);
95 assert_se(r >= 0);
96
97 r = sd_bus_set_address(b, address);
98 assert_se(r >= 0);
99
100 r = sd_bus_start(b);
101 assert_se(r >= 0);
102
103 assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
104
105 lsize = 1;
106 rsize = MAX_SIZE;
107
31175451
KS
108 printf("SIZE\tCOPY\tMEMFD\n");
109
832d16a6 110 for (;;) {
061b2c43
LP
111 usec_t t;
112 unsigned n_copying, n_memfd;
832d16a6
LP
113
114 csize = (lsize + rsize) / 2;
115
832d16a6
LP
116 if (csize <= lsize)
117 break;
118
119 if (csize <= 0)
120 break;
8f155917 121
83d97ce6 122 printf("%zu\t", csize);
31175451 123
832d16a6 124 b->use_memfd = 0;
061b2c43 125
832d16a6 126 t = now(CLOCK_MONOTONIC);
061b2c43 127 for (n_copying = 0;; n_copying++) {
832d16a6 128 transaction(b, csize);
061b2c43
LP
129 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
130 break;
131 }
31175451 132 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
061b2c43 133
832d16a6 134 b->use_memfd = -1;
061b2c43 135
832d16a6 136 t = now(CLOCK_MONOTONIC);
061b2c43 137 for (n_memfd = 0;; n_memfd++) {
832d16a6 138 transaction(b, csize);
061b2c43
LP
139 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
140 break;
141 }
6cbf6931 142 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
061b2c43
LP
143
144 if (n_copying == n_memfd)
832d16a6
LP
145 break;
146
061b2c43 147 if (n_copying > n_memfd)
832d16a6
LP
148 lsize = csize;
149 else
150 rsize = csize;
8f155917
LP
151 }
152
31175451
KS
153 b->use_memfd = 1;
154 assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Exit", &x) >= 0);
155 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
156 assert_se(sd_bus_send(b, x, NULL) >= 0);
157
158 sd_bus_unref(b);
159}
160
161static void client_chart(const char *address) {
162 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
163 size_t csize;
164 sd_bus *b;
165 int r;
166
167 r = sd_bus_new(&b);
168 assert_se(r >= 0);
169
170 r = sd_bus_set_address(b, address);
171 assert_se(r >= 0);
172
173 r = sd_bus_start(b);
174 assert_se(r >= 0);
175
176 assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
177
178 printf("SIZE\tCOPY\tMEMFD\n");
179
83d97ce6 180 for (csize = 1; csize <= MAX_SIZE; csize *= 2) {
31175451
KS
181 usec_t t;
182 unsigned n_copying, n_memfd;
183
83d97ce6 184 printf("%zu\t", csize);
31175451
KS
185
186 b->use_memfd = 0;
187
188 t = now(CLOCK_MONOTONIC);
189 for (n_copying = 0;; n_copying++) {
190 transaction(b, csize);
191 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
192 break;
193 }
194
195 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
196
197 b->use_memfd = -1;
198
199 t = now(CLOCK_MONOTONIC);
200 for (n_memfd = 0;; n_memfd++) {
201 transaction(b, csize);
202 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
203 break;
204 }
205
206 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
207 }
208
209 b->use_memfd = 1;
832d16a6
LP
210 assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Exit", &x) >= 0);
211 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
212 assert_se(sd_bus_send(b, x, NULL) >= 0);
8f155917 213
832d16a6 214 sd_bus_unref(b);
8f155917
LP
215}
216
832d16a6 217int main(int argc, char *argv[]) {
31175451
KS
218 enum {
219 MODE_BISECT,
220 MODE_CHART,
221 } mode = MODE_BISECT;
222 int i;
8f155917 223 _cleanup_free_ char *bus_name = NULL, *address = NULL;
832d16a6
LP
224 _cleanup_close_ int bus_ref = -1;
225 cpu_set_t cpuset;
226 size_t result;
8f155917 227 sd_bus *b;
8f155917 228 pid_t pid;
832d16a6
LP
229 int r;
230
31175451
KS
231 for (i = 1; i < argc; i++) {
232 if (streq(argv[i], "chart")) {
233 mode = MODE_CHART;
234 continue;
235 }
236
237 assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
238 }
061b2c43
LP
239
240 assert_se(arg_loop_usec > 0);
241
8f155917
LP
242 bus_ref = bus_kernel_create("deine-mutter", &bus_name);
243 if (bus_ref == -ENOENT)
244 exit(EXIT_TEST_SKIP);
245
246 assert_se(bus_ref >= 0);
247
248 address = strappend("kernel:path=", bus_name);
249 assert_se(address);
250
251 r = sd_bus_new(&b);
252 assert_se(r >= 0);
253
8f155917
LP
254 r = sd_bus_set_address(b, address);
255 assert_se(r >= 0);
256
257 r = sd_bus_start(b);
258 assert_se(r >= 0);
259
832d16a6
LP
260 sync();
261 setpriority(PRIO_PROCESS, 0, -19);
262
8f155917
LP
263 pid = fork();
264 assert_se(pid >= 0);
265
266 if (pid == 0) {
832d16a6
LP
267 CPU_ZERO(&cpuset);
268 CPU_SET(0, &cpuset);
269 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
270
8f155917
LP
271 close_nointr_nofail(bus_ref);
272 sd_bus_unref(b);
273
31175451
KS
274 switch (mode) {
275 case MODE_BISECT:
276 client_bisect(address);
277 break;
278
279 case MODE_CHART:
280 client_chart(address);
281 break;
282 }
283
8f155917
LP
284 _exit(0);
285 }
286
832d16a6
LP
287 CPU_ZERO(&cpuset);
288 CPU_SET(1, &cpuset);
289 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
8f155917 290
832d16a6 291 server(b, &result);
8f155917 292
31175451
KS
293 if (mode == MODE_BISECT)
294 printf("Copying/memfd are equally fast at %zu bytes\n", result);
8f155917 295
832d16a6 296 assert_se(waitpid(pid, NULL, 0) == pid);
8f155917 297
832d16a6 298 sd_bus_unref(b);
8f155917
LP
299
300 return 0;
301}