]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/test-bus-benchmark.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #include "alloc-util.h"
8 #include "bus-internal.h"
9 #include "bus-kernel.h"
13 #include "time-util.h"
16 #define MAX_SIZE (2*1024*1024)
18 static usec_t arg_loop_usec
= 100 * USEC_PER_MSEC
;
25 static void server(sd_bus
*b
, size_t *result
) {
29 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
31 r
= sd_bus_process(b
, &m
);
35 assert_se(sd_bus_wait(b
, USEC_INFINITY
) >= 0);
39 if (sd_bus_message_is_method_call(m
, "benchmark.server", "Ping"))
40 assert_se(sd_bus_reply_method_return(m
, NULL
) >= 0);
41 else if (sd_bus_message_is_method_call(m
, "benchmark.server", "Work")) {
45 /* Make sure the mmap is mapped */
46 assert_se(sd_bus_message_read_array(m
, 'y', &p
, &sz
) > 0);
48 r
= sd_bus_reply_method_return(m
, NULL
);
50 } else if (sd_bus_message_is_method_call(m
, "benchmark.server", "Exit")) {
52 assert_se(sd_bus_message_read(m
, "t", &res
) > 0);
57 } else if (!sd_bus_message_is_signal(m
, NULL
, NULL
))
58 assert_not_reached("Unknown method");
62 static void transaction(sd_bus
*b
, size_t sz
, const char *server_name
) {
63 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
66 assert_se(sd_bus_message_new_method_call(b
, &m
, server_name
, "/", "benchmark.server", "Work") >= 0);
67 assert_se(sd_bus_message_append_array_space(m
, 'y', sz
, (void**) &p
) >= 0);
71 assert_se(sd_bus_call(b
, m
, 0, NULL
, &reply
) >= 0);
74 static void client_bisect(const char *address
, const char *server_name
) {
75 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*x
= NULL
;
76 size_t lsize
, rsize
, csize
;
83 r
= sd_bus_set_address(b
, address
);
89 r
= sd_bus_call_method(b
, server_name
, "/", "benchmark.server", "Ping", NULL
, NULL
, NULL
);
95 printf("SIZE\tCOPY\tMEMFD\n");
99 unsigned n_copying
, n_memfd
;
101 csize
= (lsize
+ rsize
) / 2;
109 printf("%zu\t", csize
);
113 t
= now(CLOCK_MONOTONIC
);
114 for (n_copying
= 0;; n_copying
++) {
115 transaction(b
, csize
, server_name
);
116 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
119 printf("%u\t", (unsigned) ((n_copying
* USEC_PER_SEC
) / arg_loop_usec
));
123 t
= now(CLOCK_MONOTONIC
);
124 for (n_memfd
= 0;; n_memfd
++) {
125 transaction(b
, csize
, server_name
);
126 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
129 printf("%u\n", (unsigned) ((n_memfd
* USEC_PER_SEC
) / arg_loop_usec
));
131 if (n_copying
== n_memfd
)
134 if (n_copying
> n_memfd
)
141 assert_se(sd_bus_message_new_method_call(b
, &x
, server_name
, "/", "benchmark.server", "Exit") >= 0);
142 assert_se(sd_bus_message_append(x
, "t", csize
) >= 0);
143 assert_se(sd_bus_send(b
, x
, NULL
) >= 0);
148 static void client_chart(Type type
, const char *address
, const char *server_name
, int fd
) {
149 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*x
= NULL
;
157 if (type
== TYPE_DIRECT
) {
158 r
= sd_bus_set_fd(b
, fd
, fd
);
161 r
= sd_bus_set_address(b
, address
);
164 r
= sd_bus_set_bus_client(b
, true);
171 r
= sd_bus_call_method(b
, server_name
, "/", "benchmark.server", "Ping", NULL
, NULL
, NULL
);
176 printf("SIZE\tLEGACY\n");
179 printf("SIZE\tDIRECT\n");
183 for (csize
= 1; csize
<= MAX_SIZE
; csize
*= 2) {
187 printf("%zu\t", csize
);
189 t
= now(CLOCK_MONOTONIC
);
190 for (n_memfd
= 0;; n_memfd
++) {
191 transaction(b
, csize
, server_name
);
192 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
196 printf("%u\n", (unsigned) ((n_memfd
* USEC_PER_SEC
) / arg_loop_usec
));
200 assert_se(sd_bus_message_new_method_call(b
, &x
, server_name
, "/", "benchmark.server", "Exit") >= 0);
201 assert_se(sd_bus_message_append(x
, "t", csize
) >= 0);
202 assert_se(sd_bus_send(b
, x
, NULL
) >= 0);
207 int main(int argc
, char *argv
[]) {
211 } mode
= MODE_BISECT
;
212 Type type
= TYPE_LEGACY
;
213 int i
, pair
[2] = { -1, -1 };
214 _cleanup_free_
char *address
= NULL
, *server_name
= NULL
;
215 _cleanup_close_
int bus_ref
= -1;
223 for (i
= 1; i
< argc
; i
++) {
224 if (streq(argv
[i
], "chart")) {
227 } else if (streq(argv
[i
], "legacy")) {
230 } else if (streq(argv
[i
], "direct")) {
235 assert_se(parse_sec(argv
[i
], &arg_loop_usec
) >= 0);
238 assert_se(arg_loop_usec
> 0);
240 if (type
== TYPE_LEGACY
) {
243 e
= secure_getenv("DBUS_SESSION_BUS_ADDRESS");
253 if (type
== TYPE_DIRECT
) {
254 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
, 0, pair
) >= 0);
256 r
= sd_bus_set_fd(b
, pair
[0], pair
[0]);
259 r
= sd_bus_set_server(b
, true, SD_ID128_NULL
);
262 r
= sd_bus_set_address(b
, address
);
265 r
= sd_bus_set_bus_client(b
, true);
272 if (type
!= TYPE_DIRECT
) {
273 r
= sd_bus_get_unique_name(b
, &unique
);
276 server_name
= strdup(unique
);
277 assert_se(server_name
);
281 setpriority(PRIO_PROCESS
, 0, -19);
289 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
296 client_bisect(address
, server_name
);
300 client_chart(type
, address
, server_name
, pair
[1]);
309 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
313 if (mode
== MODE_BISECT
)
314 printf("Copying/memfd are equally fast at %zu bytes\n", result
);
316 assert_se(waitpid(pid
, NULL
, 0) == pid
);