1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
26 #include "time-util.h"
29 #include "bus-kernel.h"
30 #include "bus-internal.h"
32 #define MAX_SIZE (2*1024*1024)
34 static usec_t arg_loop_usec
= 100 * USEC_PER_MSEC
;
42 static void server(sd_bus
*b
, size_t *result
) {
46 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
48 r
= sd_bus_process(b
, &m
);
52 assert_se(sd_bus_wait(b
, USEC_INFINITY
) >= 0);
56 if (sd_bus_message_is_method_call(m
, "benchmark.server", "Ping"))
57 assert_se(sd_bus_reply_method_return(m
, NULL
) >= 0);
58 else if (sd_bus_message_is_method_call(m
, "benchmark.server", "Work")) {
62 /* Make sure the mmap is mapped */
63 assert_se(sd_bus_message_read_array(m
, 'y', &p
, &sz
) > 0);
65 r
= sd_bus_reply_method_return(m
, NULL
);
67 } else if (sd_bus_message_is_method_call(m
, "benchmark.server", "Exit")) {
69 assert_se(sd_bus_message_read(m
, "t", &res
) > 0);
74 } else if (!sd_bus_message_is_signal(m
, NULL
, NULL
))
75 assert_not_reached("Unknown method");
79 static void transaction(sd_bus
*b
, size_t sz
, const char *server_name
) {
80 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
83 assert_se(sd_bus_message_new_method_call(b
, &m
, server_name
, "/", "benchmark.server", "Work") >= 0);
84 assert_se(sd_bus_message_append_array_space(m
, 'y', sz
, (void**) &p
) >= 0);
88 assert_se(sd_bus_call(b
, m
, 0, NULL
, &reply
) >= 0);
91 static void client_bisect(const char *address
, const char *server_name
) {
92 _cleanup_bus_message_unref_ sd_bus_message
*x
= NULL
;
93 size_t lsize
, rsize
, csize
;
100 r
= sd_bus_set_address(b
, address
);
106 r
= sd_bus_call_method(b
, server_name
, "/", "benchmark.server", "Ping", NULL
, NULL
, NULL
);
112 printf("SIZE\tCOPY\tMEMFD\n");
116 unsigned n_copying
, n_memfd
;
118 csize
= (lsize
+ rsize
) / 2;
126 printf("%zu\t", csize
);
130 t
= now(CLOCK_MONOTONIC
);
131 for (n_copying
= 0;; n_copying
++) {
132 transaction(b
, csize
, server_name
);
133 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
136 printf("%u\t", (unsigned) ((n_copying
* USEC_PER_SEC
) / arg_loop_usec
));
140 t
= now(CLOCK_MONOTONIC
);
141 for (n_memfd
= 0;; n_memfd
++) {
142 transaction(b
, csize
, server_name
);
143 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
146 printf("%u\n", (unsigned) ((n_memfd
* USEC_PER_SEC
) / arg_loop_usec
));
148 if (n_copying
== n_memfd
)
151 if (n_copying
> n_memfd
)
158 assert_se(sd_bus_message_new_method_call(b
, &x
, server_name
, "/", "benchmark.server", "Exit") >= 0);
159 assert_se(sd_bus_message_append(x
, "t", csize
) >= 0);
160 assert_se(sd_bus_send(b
, x
, NULL
) >= 0);
165 static void client_chart(Type type
, const char *address
, const char *server_name
, int fd
) {
166 _cleanup_bus_message_unref_ sd_bus_message
*x
= NULL
;
174 if (type
== TYPE_DIRECT
) {
175 r
= sd_bus_set_fd(b
, fd
, fd
);
178 r
= sd_bus_set_address(b
, address
);
181 r
= sd_bus_set_bus_client(b
, true);
188 r
= sd_bus_call_method(b
, server_name
, "/", "benchmark.server", "Ping", NULL
, NULL
, NULL
);
193 printf("SIZE\tCOPY\tMEMFD\n");
196 printf("SIZE\tLEGACY\n");
199 printf("SIZE\tDIRECT\n");
203 for (csize
= 1; csize
<= MAX_SIZE
; csize
*= 2) {
205 unsigned n_copying
, n_memfd
;
207 printf("%zu\t", csize
);
209 if (type
== TYPE_KDBUS
) {
212 t
= now(CLOCK_MONOTONIC
);
213 for (n_copying
= 0;; n_copying
++) {
214 transaction(b
, csize
, server_name
);
215 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
219 printf("%u\t", (unsigned) ((n_copying
* USEC_PER_SEC
) / arg_loop_usec
));
224 t
= now(CLOCK_MONOTONIC
);
225 for (n_memfd
= 0;; n_memfd
++) {
226 transaction(b
, csize
, server_name
);
227 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
231 printf("%u\n", (unsigned) ((n_memfd
* USEC_PER_SEC
) / arg_loop_usec
));
235 assert_se(sd_bus_message_new_method_call(b
, &x
, server_name
, "/", "benchmark.server", "Exit") >= 0);
236 assert_se(sd_bus_message_append(x
, "t", csize
) >= 0);
237 assert_se(sd_bus_send(b
, x
, NULL
) >= 0);
242 int main(int argc
, char *argv
[]) {
246 } mode
= MODE_BISECT
;
247 Type type
= TYPE_KDBUS
;
248 int i
, pair
[2] = { -1, -1 };
249 _cleanup_free_
char *name
= NULL
, *bus_name
= NULL
, *address
= NULL
, *server_name
= NULL
;
250 _cleanup_close_
int bus_ref
= -1;
258 for (i
= 1; i
< argc
; i
++) {
259 if (streq(argv
[i
], "chart")) {
262 } else if (streq(argv
[i
], "legacy")) {
265 } else if (streq(argv
[i
], "direct")) {
270 assert_se(parse_sec(argv
[i
], &arg_loop_usec
) >= 0);
273 assert_se(!MODE_BISECT
|| TYPE_KDBUS
);
275 assert_se(arg_loop_usec
> 0);
277 if (type
== TYPE_KDBUS
) {
278 assert_se(asprintf(&name
, "deine-mutter-%u", (unsigned) getpid()) >= 0);
280 bus_ref
= bus_kernel_create_bus(name
, false, &bus_name
);
281 if (bus_ref
== -ENOENT
)
282 exit(EXIT_TEST_SKIP
);
284 assert_se(bus_ref
>= 0);
286 address
= strappend("kernel:path=", bus_name
);
288 } else if (type
== TYPE_LEGACY
) {
291 e
= secure_getenv("DBUS_SESSION_BUS_ADDRESS");
301 if (type
== TYPE_DIRECT
) {
302 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
, 0, pair
) >= 0);
304 r
= sd_bus_set_fd(b
, pair
[0], pair
[0]);
307 r
= sd_bus_set_server(b
, true, SD_ID128_NULL
);
310 r
= sd_bus_set_address(b
, address
);
313 r
= sd_bus_set_bus_client(b
, true);
320 if (type
!= TYPE_DIRECT
) {
321 r
= sd_bus_get_unique_name(b
, &unique
);
324 server_name
= strdup(unique
);
325 assert_se(server_name
);
329 setpriority(PRIO_PROCESS
, 0, -19);
337 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
344 client_bisect(address
, server_name
);
348 client_chart(type
, address
, server_name
, pair
[1]);
357 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
361 if (mode
== MODE_BISECT
)
362 printf("Copying/memfd are equally fast at %zu bytes\n", result
);
364 assert_se(waitpid(pid
, NULL
, 0) == pid
);