]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/test-bus-benchmark.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "alloc-util.h"
26 #include "bus-internal.h"
27 #include "bus-kernel.h"
31 #include "time-util.h"
34 #define MAX_SIZE (2*1024*1024)
36 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\tLEGACY\n");
197 printf("SIZE\tDIRECT\n");
201 for (csize
= 1; csize
<= MAX_SIZE
; csize
*= 2) {
205 printf("%zu\t", csize
);
207 t
= now(CLOCK_MONOTONIC
);
208 for (n_memfd
= 0;; n_memfd
++) {
209 transaction(b
, csize
, server_name
);
210 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
214 printf("%u\n", (unsigned) ((n_memfd
* USEC_PER_SEC
) / arg_loop_usec
));
218 assert_se(sd_bus_message_new_method_call(b
, &x
, server_name
, "/", "benchmark.server", "Exit") >= 0);
219 assert_se(sd_bus_message_append(x
, "t", csize
) >= 0);
220 assert_se(sd_bus_send(b
, x
, NULL
) >= 0);
225 int main(int argc
, char *argv
[]) {
229 } mode
= MODE_BISECT
;
230 Type type
= TYPE_LEGACY
;
231 int i
, pair
[2] = { -1, -1 };
232 _cleanup_free_
char *address
= NULL
, *server_name
= NULL
;
233 _cleanup_close_
int bus_ref
= -1;
241 for (i
= 1; i
< argc
; i
++) {
242 if (streq(argv
[i
], "chart")) {
245 } else if (streq(argv
[i
], "legacy")) {
248 } else if (streq(argv
[i
], "direct")) {
253 assert_se(parse_sec(argv
[i
], &arg_loop_usec
) >= 0);
256 assert_se(arg_loop_usec
> 0);
258 if (type
== TYPE_LEGACY
) {
261 e
= secure_getenv("DBUS_SESSION_BUS_ADDRESS");
271 if (type
== TYPE_DIRECT
) {
272 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
, 0, pair
) >= 0);
274 r
= sd_bus_set_fd(b
, pair
[0], pair
[0]);
277 r
= sd_bus_set_server(b
, true, SD_ID128_NULL
);
280 r
= sd_bus_set_address(b
, address
);
283 r
= sd_bus_set_bus_client(b
, true);
290 if (type
!= TYPE_DIRECT
) {
291 r
= sd_bus_get_unique_name(b
, &unique
);
294 server_name
= strdup(unique
);
295 assert_se(server_name
);
299 setpriority(PRIO_PROCESS
, 0, -19);
307 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
314 client_bisect(address
, server_name
);
318 client_chart(type
, address
, server_name
, pair
[1]);
327 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
331 if (mode
== MODE_BISECT
)
332 printf("Copying/memfd are equally fast at %zu bytes\n", result
);
334 assert_se(waitpid(pid
, NULL
, 0) == pid
);