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