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"
35 #define MAX_SIZE (4*1024*1024)
37 static usec_t arg_loop_usec = 100 * USEC_PER_MSEC;
39 static void server(sd_bus *b, size_t *result) {
43 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
45 r = sd_bus_process(b, &m);
49 assert_se(sd_bus_wait(b, (usec_t) -1) >= 0);
53 if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping"))
54 assert_se(sd_bus_reply_method_return(b, m, NULL) >= 0);
55 else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) {
59 /* Make sure the mmap is mapped */
60 assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0);
62 assert_se(sd_bus_reply_method_return(b, m, NULL) >= 0);
63 } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) {
65 assert_se(sd_bus_message_read(m, "t", &res) > 0);
71 assert_not_reached("Unknown method");
75 static void transaction(sd_bus *b, size_t sz) {
76 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
79 assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Work", &m) >= 0);
80 assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0);
84 assert_se(sd_bus_send_with_reply_and_block(b, m, 0, NULL, &reply) >= 0);
87 static void client_bisect(const char *address) {
88 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
89 size_t lsize, rsize, csize;
96 r = sd_bus_set_address(b, address);
102 assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
107 printf("SIZE\tCOPY\tMEMFD\n");
111 unsigned n_copying, n_memfd;
113 csize = (lsize + rsize) / 2;
121 printf("%zu\t", csize);
125 t = now(CLOCK_MONOTONIC);
126 for (n_copying = 0;; n_copying++) {
127 transaction(b, csize);
128 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
131 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
135 t = now(CLOCK_MONOTONIC);
136 for (n_memfd = 0;; n_memfd++) {
137 transaction(b, csize);
138 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
141 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
143 if (n_copying == n_memfd)
146 if (n_copying > n_memfd)
153 assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Exit", &x) >= 0);
154 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
155 assert_se(sd_bus_send(b, x, NULL) >= 0);
160 static void client_chart(const char *address) {
161 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
169 r = sd_bus_set_address(b, address);
175 assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
177 printf("SIZE\tCOPY\tMEMFD\n");
179 for (csize = 1; csize <= MAX_SIZE; csize *= 2) {
181 unsigned n_copying, n_memfd;
183 printf("%zu\t", csize);
187 t = now(CLOCK_MONOTONIC);
188 for (n_copying = 0;; n_copying++) {
189 transaction(b, csize);
190 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
194 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
198 t = now(CLOCK_MONOTONIC);
199 for (n_memfd = 0;; n_memfd++) {
200 transaction(b, csize);
201 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
205 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
209 assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Exit", &x) >= 0);
210 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
211 assert_se(sd_bus_send(b, x, NULL) >= 0);
216 int main(int argc, char *argv[]) {
220 } mode = MODE_BISECT;
222 _cleanup_free_ char *bus_name = NULL, *address = NULL;
223 _cleanup_close_ int bus_ref = -1;
230 log_set_max_level(LOG_DEBUG);
232 for (i = 1; i < argc; i++) {
233 if (streq(argv[i], "chart")) {
238 assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
241 assert_se(arg_loop_usec > 0);
243 bus_ref = bus_kernel_create("deine-mutter", &bus_name);
244 if (bus_ref == -ENOENT)
245 exit(EXIT_TEST_SKIP);
247 assert_se(bus_ref >= 0);
249 address = strappend("kernel:path=", bus_name);
255 r = sd_bus_set_address(b, address);
262 setpriority(PRIO_PROCESS, 0, -19);
270 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
272 close_nointr_nofail(bus_ref);
277 client_bisect(address);
281 client_chart(address);
290 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
294 if (mode == MODE_BISECT)
295 printf("Copying/memfd are equally fast at %zu bytes\n", result);
297 assert_se(waitpid(pid, NULL, 0) == pid);