]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/test-bus-benchmark.c
2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
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.
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.
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/>.
24 #include "alloc-util.h"
25 #include "bus-internal.h"
26 #include "bus-kernel.h"
30 #include "time-util.h"
33 #define MAX_SIZE (2*1024*1024)
35 static usec_t arg_loop_usec
= 100 * USEC_PER_MSEC
;
43 static void server(sd_bus
*b
, size_t *result
) {
47 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
49 r
= sd_bus_process(b
, &m
);
53 assert_se(sd_bus_wait(b
, USEC_INFINITY
) >= 0);
57 if (sd_bus_message_is_method_call(m
, "benchmark.server", "Ping"))
58 assert_se(sd_bus_reply_method_return(m
, NULL
) >= 0);
59 else if (sd_bus_message_is_method_call(m
, "benchmark.server", "Work")) {
63 /* Make sure the mmap is mapped */
64 assert_se(sd_bus_message_read_array(m
, 'y', &p
, &sz
) > 0);
66 r
= sd_bus_reply_method_return(m
, NULL
);
68 } else if (sd_bus_message_is_method_call(m
, "benchmark.server", "Exit")) {
70 assert_se(sd_bus_message_read(m
, "t", &res
) > 0);
75 } else if (!sd_bus_message_is_signal(m
, NULL
, NULL
))
76 assert_not_reached("Unknown method");
80 static void transaction(sd_bus
*b
, size_t sz
, const char *server_name
) {
81 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
84 assert_se(sd_bus_message_new_method_call(b
, &m
, server_name
, "/", "benchmark.server", "Work") >= 0);
85 assert_se(sd_bus_message_append_array_space(m
, 'y', sz
, (void**) &p
) >= 0);
89 assert_se(sd_bus_call(b
, m
, 0, NULL
, &reply
) >= 0);
92 static void client_bisect(const char *address
, const char *server_name
) {
93 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*x
= NULL
;
94 size_t lsize
, rsize
, csize
;
101 r
= sd_bus_set_address(b
, address
);
107 r
= sd_bus_call_method(b
, server_name
, "/", "benchmark.server", "Ping", NULL
, NULL
, NULL
);
113 printf("SIZE\tCOPY\tMEMFD\n");
117 unsigned n_copying
, n_memfd
;
119 csize
= (lsize
+ rsize
) / 2;
127 printf("%zu\t", csize
);
131 t
= now(CLOCK_MONOTONIC
);
132 for (n_copying
= 0;; n_copying
++) {
133 transaction(b
, csize
, server_name
);
134 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
137 printf("%u\t", (unsigned) ((n_copying
* USEC_PER_SEC
) / arg_loop_usec
));
141 t
= now(CLOCK_MONOTONIC
);
142 for (n_memfd
= 0;; n_memfd
++) {
143 transaction(b
, csize
, server_name
);
144 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
147 printf("%u\n", (unsigned) ((n_memfd
* USEC_PER_SEC
) / arg_loop_usec
));
149 if (n_copying
== n_memfd
)
152 if (n_copying
> n_memfd
)
159 assert_se(sd_bus_message_new_method_call(b
, &x
, server_name
, "/", "benchmark.server", "Exit") >= 0);
160 assert_se(sd_bus_message_append(x
, "t", csize
) >= 0);
161 assert_se(sd_bus_send(b
, x
, NULL
) >= 0);
166 static void client_chart(Type type
, const char *address
, const char *server_name
, int fd
) {
167 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*x
= NULL
;
175 if (type
== TYPE_DIRECT
) {
176 r
= sd_bus_set_fd(b
, fd
, fd
);
179 r
= sd_bus_set_address(b
, address
);
182 r
= sd_bus_set_bus_client(b
, true);
189 r
= sd_bus_call_method(b
, server_name
, "/", "benchmark.server", "Ping", NULL
, NULL
, NULL
);
194 printf("SIZE\tCOPY\tMEMFD\n");
197 printf("SIZE\tLEGACY\n");
200 printf("SIZE\tDIRECT\n");
204 for (csize
= 1; csize
<= MAX_SIZE
; csize
*= 2) {
206 unsigned n_copying
, n_memfd
;
208 printf("%zu\t", csize
);
210 if (type
== TYPE_KDBUS
) {
213 t
= now(CLOCK_MONOTONIC
);
214 for (n_copying
= 0;; n_copying
++) {
215 transaction(b
, csize
, server_name
);
216 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
220 printf("%u\t", (unsigned) ((n_copying
* USEC_PER_SEC
) / arg_loop_usec
));
225 t
= now(CLOCK_MONOTONIC
);
226 for (n_memfd
= 0;; n_memfd
++) {
227 transaction(b
, csize
, server_name
);
228 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
232 printf("%u\n", (unsigned) ((n_memfd
* USEC_PER_SEC
) / arg_loop_usec
));
236 assert_se(sd_bus_message_new_method_call(b
, &x
, server_name
, "/", "benchmark.server", "Exit") >= 0);
237 assert_se(sd_bus_message_append(x
, "t", csize
) >= 0);
238 assert_se(sd_bus_send(b
, x
, NULL
) >= 0);
243 int main(int argc
, char *argv
[]) {
247 } mode
= MODE_BISECT
;
248 Type type
= TYPE_KDBUS
;
249 int i
, pair
[2] = { -1, -1 };
250 _cleanup_free_
char *name
= NULL
, *bus_name
= NULL
, *address
= NULL
, *server_name
= NULL
;
251 _cleanup_close_
int bus_ref
= -1;
259 for (i
= 1; i
< argc
; i
++) {
260 if (streq(argv
[i
], "chart")) {
263 } else if (streq(argv
[i
], "legacy")) {
266 } else if (streq(argv
[i
], "direct")) {
271 assert_se(parse_sec(argv
[i
], &arg_loop_usec
) >= 0);
274 assert_se(!MODE_BISECT
|| TYPE_KDBUS
);
276 assert_se(arg_loop_usec
> 0);
278 if (type
== TYPE_KDBUS
) {
279 assert_se(asprintf(&name
, "deine-mutter-%u", (unsigned) getpid()) >= 0);
281 bus_ref
= bus_kernel_create_bus(name
, false, &bus_name
);
282 if (bus_ref
== -ENOENT
)
283 exit(EXIT_TEST_SKIP
);
285 assert_se(bus_ref
>= 0);
287 address
= strappend("kernel:path=", bus_name
);
289 } else if (type
== TYPE_LEGACY
) {
292 e
= secure_getenv("DBUS_SESSION_BUS_ADDRESS");
302 if (type
== TYPE_DIRECT
) {
303 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
, 0, pair
) >= 0);
305 r
= sd_bus_set_fd(b
, pair
[0], pair
[0]);
308 r
= sd_bus_set_server(b
, true, SD_ID128_NULL
);
311 r
= sd_bus_set_address(b
, address
);
314 r
= sd_bus_set_bus_client(b
, true);
321 if (type
!= TYPE_DIRECT
) {
322 r
= sd_bus_get_unique_name(b
, &unique
);
325 server_name
= strdup(unique
);
326 assert_se(server_name
);
330 setpriority(PRIO_PROCESS
, 0, -19);
338 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
345 client_bisect(address
, server_name
);
349 client_chart(type
, address
, server_name
, pair
[1]);
358 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
362 if (mode
== MODE_BISECT
)
363 printf("Copying/memfd are equally fast at %zu bytes\n", result
);
365 assert_se(waitpid(pid
, NULL
, 0) == pid
);