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