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