]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/test-bus-kernel-benchmark.c
tmpfiles: accurately report creation results
[thirdparty/systemd.git] / src / libsystemd / sd-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
1679ddc4 36#define MAX_SIZE (2*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)
3a43da28 50 assert_se(sd_bus_wait(b, USEC_INFINITY) >= 0);
8f155917
LP
51 if (!m)
52 continue;
53
832d16a6 54 if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping"))
df2d202e 55 assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
832d16a6
LP
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
df2d202e 63 assert_se(sd_bus_reply_method_return(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 79
151b9b96 80 assert_se(sd_bus_message_new_method_call(b, &m, ":1.1", "/", "benchmark.server", "Work") >= 0);
8f155917
LP
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 153 b->use_memfd = 1;
151b9b96 154 assert_se(sd_bus_message_new_method_call(b, &x, ":1.1", "/", "benchmark.server", "Exit") >= 0);
31175451
KS
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;
151b9b96 210 assert_se(sd_bus_message_new_method_call(b, &x, ":1.1", "/", "benchmark.server", "Exit") >= 0);
832d16a6
LP
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;
79ccff06 223 _cleanup_free_ char *name = NULL, *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
79ccff06
ZJS
242 assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
243
244 bus_ref = bus_kernel_create_bus(name, false, &bus_name);
8f155917
LP
245 if (bus_ref == -ENOENT)
246 exit(EXIT_TEST_SKIP);
247
248 assert_se(bus_ref >= 0);
249
250 address = strappend("kernel:path=", bus_name);
251 assert_se(address);
252
253 r = sd_bus_new(&b);
254 assert_se(r >= 0);
255
8f155917
LP
256 r = sd_bus_set_address(b, address);
257 assert_se(r >= 0);
258
259 r = sd_bus_start(b);
260 assert_se(r >= 0);
261
832d16a6
LP
262 sync();
263 setpriority(PRIO_PROCESS, 0, -19);
264
8f155917
LP
265 pid = fork();
266 assert_se(pid >= 0);
267
268 if (pid == 0) {
832d16a6
LP
269 CPU_ZERO(&cpuset);
270 CPU_SET(0, &cpuset);
271 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
272
03e334a1 273 safe_close(bus_ref);
8f155917
LP
274 sd_bus_unref(b);
275
31175451
KS
276 switch (mode) {
277 case MODE_BISECT:
278 client_bisect(address);
279 break;
280
281 case MODE_CHART:
282 client_chart(address);
283 break;
284 }
285
8f155917
LP
286 _exit(0);
287 }
288
832d16a6
LP
289 CPU_ZERO(&cpuset);
290 CPU_SET(1, &cpuset);
291 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
8f155917 292
832d16a6 293 server(b, &result);
8f155917 294
31175451
KS
295 if (mode == MODE_BISECT)
296 printf("Copying/memfd are equally fast at %zu bytes\n", result);
8f155917 297
832d16a6 298 assert_se(waitpid(pid, NULL, 0) == pid);
8f155917 299
832d16a6 300 sd_bus_unref(b);
8f155917
LP
301
302 return 0;
303}