]>
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
;
42 static void server(sd_bus
*b
, size_t *result
) {
46 _cleanup_(sd_bus_message_unrefp
) 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_(sd_bus_message_unrefp
) 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_(sd_bus_message_unrefp
) 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_(sd_bus_message_unrefp
) 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\tLEGACY\n");
196 printf("SIZE\tDIRECT\n");
200 for (csize
= 1; csize
<= MAX_SIZE
; csize
*= 2) {
204 printf("%zu\t", csize
);
206 t
= now(CLOCK_MONOTONIC
);
207 for (n_memfd
= 0;; n_memfd
++) {
208 transaction(b
, csize
, server_name
);
209 if (now(CLOCK_MONOTONIC
) >= t
+ arg_loop_usec
)
213 printf("%u\n", (unsigned) ((n_memfd
* USEC_PER_SEC
) / arg_loop_usec
));
217 assert_se(sd_bus_message_new_method_call(b
, &x
, server_name
, "/", "benchmark.server", "Exit") >= 0);
218 assert_se(sd_bus_message_append(x
, "t", csize
) >= 0);
219 assert_se(sd_bus_send(b
, x
, NULL
) >= 0);
224 int main(int argc
, char *argv
[]) {
228 } mode
= MODE_BISECT
;
229 Type type
= TYPE_LEGACY
;
230 int i
, pair
[2] = { -1, -1 };
231 _cleanup_free_
char *name
= NULL
, *bus_name
= NULL
, *address
= NULL
, *server_name
= NULL
;
232 _cleanup_close_
int bus_ref
= -1;
240 for (i
= 1; i
< argc
; i
++) {
241 if (streq(argv
[i
], "chart")) {
244 } else if (streq(argv
[i
], "legacy")) {
247 } else if (streq(argv
[i
], "direct")) {
252 assert_se(parse_sec(argv
[i
], &arg_loop_usec
) >= 0);
255 assert_se(arg_loop_usec
> 0);
257 if (type
== TYPE_LEGACY
) {
260 e
= secure_getenv("DBUS_SESSION_BUS_ADDRESS");
270 if (type
== TYPE_DIRECT
) {
271 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
, 0, pair
) >= 0);
273 r
= sd_bus_set_fd(b
, pair
[0], pair
[0]);
276 r
= sd_bus_set_server(b
, true, SD_ID128_NULL
);
279 r
= sd_bus_set_address(b
, address
);
282 r
= sd_bus_set_bus_client(b
, true);
289 if (type
!= TYPE_DIRECT
) {
290 r
= sd_bus_get_unique_name(b
, &unique
);
293 server_name
= strdup(unique
);
294 assert_se(server_name
);
298 setpriority(PRIO_PROCESS
, 0, -19);
306 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
313 client_bisect(address
, server_name
);
317 client_chart(type
, address
, server_name
, pair
[1]);
326 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t
), &cpuset
);
330 if (mode
== MODE_BISECT
)
331 printf("Copying/memfd are equally fast at %zu bytes\n", result
);
333 assert_se(waitpid(pid
, NULL
, 0) == pid
);