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/>.
27 #include "time-util.h"
30 #include "bus-message.h"
31 #include "bus-error.h"
32 #include "bus-kernel.h"
33 #include "bus-internal.h"
36 #define MAX_SIZE (4*1024*1024)
38 static usec_t arg_loop_usec = 100 * USEC_PER_MSEC;
40 static void server(sd_bus *b, size_t *result) {
44 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
46 r = sd_bus_process(b, &m);
50 assert_se(sd_bus_wait(b, (usec_t) -1) >= 0);
54 if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping"))
55 assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
56 else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) {
60 /* Make sure the mmap is mapped */
61 assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0);
63 assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
64 } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) {
66 assert_se(sd_bus_message_read(m, "t", &res) > 0);
72 assert_not_reached("Unknown method");
76 static void transaction(sd_bus *b, size_t sz) {
77 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
80 assert_se(sd_bus_message_new_method_call(b, &m, ":1.1", "/", "benchmark.server", "Work") >= 0);
81 assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0);
85 assert_se(sd_bus_call(b, m, 0, NULL, &reply) >= 0);
88 static void client_bisect(const char *address) {
89 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
90 size_t lsize, rsize, csize;
97 r = sd_bus_set_address(b, address);
103 assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
108 printf("SIZE\tCOPY\tMEMFD\n");
112 unsigned n_copying, n_memfd;
114 csize = (lsize + rsize) / 2;
122 printf("%zu\t", csize);
126 t = now(CLOCK_MONOTONIC);
127 for (n_copying = 0;; n_copying++) {
128 transaction(b, csize);
129 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
132 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
136 t = now(CLOCK_MONOTONIC);
137 for (n_memfd = 0;; n_memfd++) {
138 transaction(b, csize);
139 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
142 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
144 if (n_copying == n_memfd)
147 if (n_copying > n_memfd)
154 assert_se(sd_bus_message_new_method_call(b, &x, ":1.1", "/", "benchmark.server", "Exit") >= 0);
155 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
156 assert_se(sd_bus_send(b, x, NULL) >= 0);
161 static void client_chart(const char *address) {
162 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
170 r = sd_bus_set_address(b, address);
176 assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
178 printf("SIZE\tCOPY\tMEMFD\n");
180 for (csize = 1; csize <= MAX_SIZE; csize *= 2) {
182 unsigned n_copying, n_memfd;
184 printf("%zu\t", csize);
188 t = now(CLOCK_MONOTONIC);
189 for (n_copying = 0;; n_copying++) {
190 transaction(b, csize);
191 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
195 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
199 t = now(CLOCK_MONOTONIC);
200 for (n_memfd = 0;; n_memfd++) {
201 transaction(b, csize);
202 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
206 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
210 assert_se(sd_bus_message_new_method_call(b, &x, ":1.1", "/", "benchmark.server", "Exit") >= 0);
211 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
212 assert_se(sd_bus_send(b, x, NULL) >= 0);
217 int main(int argc, char *argv[]) {
221 } mode = MODE_BISECT;
223 _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
224 _cleanup_close_ int bus_ref = -1;
231 for (i = 1; i < argc; i++) {
232 if (streq(argv[i], "chart")) {
237 assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
240 assert_se(arg_loop_usec > 0);
242 assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
244 bus_ref = bus_kernel_create_bus(name, false, &bus_name);
245 if (bus_ref == -ENOENT)
246 exit(EXIT_TEST_SKIP);
248 assert_se(bus_ref >= 0);
250 address = strappend("kernel:path=", bus_name);
256 r = sd_bus_set_address(b, address);
263 setpriority(PRIO_PROCESS, 0, -19);
271 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
273 close_nointr_nofail(bus_ref);
278 client_bisect(address);
282 client_chart(address);
291 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
295 if (mode == MODE_BISECT)
296 printf("Copying/memfd are equally fast at %zu bytes\n", result);
298 assert_se(waitpid(pid, NULL, 0) == pid);