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/>.
25 #include "time-util.h"
28 #include "bus-kernel.h"
29 #include "bus-internal.h"
32 #define MAX_SIZE (2*1024*1024)
34 static usec_t arg_loop_usec = 100 * USEC_PER_MSEC;
36 static void server(sd_bus *b, size_t *result) {
40 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
42 r = sd_bus_process(b, &m);
46 assert_se(sd_bus_wait(b, USEC_INFINITY) >= 0);
50 if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping"))
51 assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
52 else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) {
56 /* Make sure the mmap is mapped */
57 assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0);
59 assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
60 } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) {
62 assert_se(sd_bus_message_read(m, "t", &res) > 0);
68 assert_not_reached("Unknown method");
72 static void transaction(sd_bus *b, size_t sz) {
73 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
76 assert_se(sd_bus_message_new_method_call(b, &m, ":1.1", "/", "benchmark.server", "Work") >= 0);
77 assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0);
81 assert_se(sd_bus_call(b, m, 0, NULL, &reply) >= 0);
84 static void client_bisect(const char *address) {
85 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
86 size_t lsize, rsize, csize;
93 r = sd_bus_set_address(b, address);
99 assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
104 printf("SIZE\tCOPY\tMEMFD\n");
108 unsigned n_copying, n_memfd;
110 csize = (lsize + rsize) / 2;
118 printf("%zu\t", csize);
122 t = now(CLOCK_MONOTONIC);
123 for (n_copying = 0;; n_copying++) {
124 transaction(b, csize);
125 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
128 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
132 t = now(CLOCK_MONOTONIC);
133 for (n_memfd = 0;; n_memfd++) {
134 transaction(b, csize);
135 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
138 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
140 if (n_copying == n_memfd)
143 if (n_copying > n_memfd)
150 assert_se(sd_bus_message_new_method_call(b, &x, ":1.1", "/", "benchmark.server", "Exit") >= 0);
151 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
152 assert_se(sd_bus_send(b, x, NULL) >= 0);
157 static void client_chart(const char *address) {
158 _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
166 r = sd_bus_set_address(b, address);
172 assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
174 printf("SIZE\tCOPY\tMEMFD\n");
176 for (csize = 1; csize <= MAX_SIZE; csize *= 2) {
178 unsigned n_copying, n_memfd;
180 printf("%zu\t", csize);
184 t = now(CLOCK_MONOTONIC);
185 for (n_copying = 0;; n_copying++) {
186 transaction(b, csize);
187 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
191 printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
195 t = now(CLOCK_MONOTONIC);
196 for (n_memfd = 0;; n_memfd++) {
197 transaction(b, csize);
198 if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
202 printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
206 assert_se(sd_bus_message_new_method_call(b, &x, ":1.1", "/", "benchmark.server", "Exit") >= 0);
207 assert_se(sd_bus_message_append(x, "t", csize) >= 0);
208 assert_se(sd_bus_send(b, x, NULL) >= 0);
213 int main(int argc, char *argv[]) {
217 } mode = MODE_BISECT;
219 _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
220 _cleanup_close_ int bus_ref = -1;
227 for (i = 1; i < argc; i++) {
228 if (streq(argv[i], "chart")) {
233 assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
236 assert_se(arg_loop_usec > 0);
238 assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
240 bus_ref = bus_kernel_create_bus(name, false, &bus_name);
241 if (bus_ref == -ENOENT)
242 exit(EXIT_TEST_SKIP);
244 assert_se(bus_ref >= 0);
246 address = strappend("kernel:path=", bus_name);
252 r = sd_bus_set_address(b, address);
259 setpriority(PRIO_PROCESS, 0, -19);
267 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
274 client_bisect(address);
278 client_chart(address);
287 pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
291 if (mode == MODE_BISECT)
292 printf("Copying/memfd are equally fast at %zu bytes\n", result);
294 assert_se(waitpid(pid, NULL, 0) == pid);