]> git.ozlabs.org Git - ccan/blob - ccan/io/benchmarks/run-loop.c
5dc1c3e11b628743165c0b2f160a04cd2fee976b
[ccan] / ccan / io / benchmarks / run-loop.c
1 #include <ccan/io/io.h>
2 #include <ccan/time/time.h>
3 #include <sys/wait.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <assert.h>
7 #include <err.h>
8 #include <signal.h>
9
10 #define NUM 500
11 #define NUM_ITERS 10000
12
13 struct buffer {
14         int iters;
15         struct io_conn *reader, *writer;
16         char buf[32];
17 };
18
19 static struct io_plan *poke_writer(struct io_conn *conn, struct buffer *buf);
20 static struct io_plan *poke_reader(struct io_conn *conn, struct buffer *buf);
21
22 static struct io_plan *do_read(struct io_conn *conn, struct buffer *buf)
23 {
24         assert(conn == buf->reader);
25
26         return io_read(conn, &buf->buf, sizeof(buf->buf), poke_writer, buf);
27 }
28
29 static struct io_plan *do_write(struct io_conn *conn, struct buffer *buf)
30 {
31         assert(conn == buf->writer);
32
33         return io_write(conn, &buf->buf, sizeof(buf->buf), poke_reader, buf);
34 }
35
36 static struct io_plan *poke_writer(struct io_conn *conn, struct buffer *buf)
37 {
38         assert(conn == buf->reader);
39
40         if (buf->iters == NUM_ITERS)
41                 return io_close(conn, NULL);
42
43         /* You write. */
44         io_wake(buf->writer, do_write, buf);
45
46         /* I'll wait until you wake me. */
47         return io_idle(conn);
48 }
49
50 static struct io_plan *poke_reader(struct io_conn *conn, struct buffer *buf)
51 {
52         assert(conn == buf->writer);
53         /* You read. */
54         io_wake(buf->reader, do_read, buf);
55
56         if (++buf->iters == NUM_ITERS)
57                 return io_close(conn, NULL);
58
59         /* I'll wait until you tell me to write. */
60         return io_idle(conn);
61 }
62
63 static struct io_plan *reader(struct io_conn *conn, struct buffer *buf)
64 {
65         assert(conn == buf->reader);
66
67         /* Wait for writer to tell us to read. */
68         return io_idle(conn);
69 }
70
71 int main(void)
72 {
73         unsigned int i;
74         int fds[2], last_read, last_write;
75         struct timespec start, end;
76         struct buffer buf[NUM];
77
78         if (pipe(fds) != 0)
79                 err(1, "pipe");
80         last_read = fds[0];
81         last_write = fds[1];
82
83         for (i = 1; i < NUM; i++) {
84                 buf[i].iters = 0;
85                 if (pipe(fds) < 0)
86                         err(1, "pipe");
87                 memset(buf[i].buf, i, sizeof(buf[i].buf));
88                 sprintf(buf[i].buf, "%i-%i", i, i);
89
90                 buf[i].reader = io_new_conn(last_read, reader, NULL, &buf[i]);
91                 if (!buf[i].reader)
92                         err(1, "Creating reader %i", i);
93                 buf[i].writer = io_new_conn(fds[1], do_write, NULL, &buf[i]);
94                 if (!buf[i].writer)
95                         err(1, "Creating writer %i", i);
96                 last_read = fds[0];
97         }
98
99         /* Last one completes the cirle. */
100         i = 0;
101         buf[i].iters = 0;
102         sprintf(buf[i].buf, "%i-%i", i, i);
103         buf[i].reader = io_new_conn(last_read, reader, NULL, &buf[i]);
104         if (!buf[i].reader)
105                 err(1, "Creating reader %i", i);
106         buf[i].writer = io_new_conn(last_write, do_write, NULL, &buf[i]);
107         if (!buf[i].writer)
108                 err(1, "Creating writer %i", i);
109
110         /* They should eventually exit */
111         start = time_now();
112         if (io_loop() != NULL)
113                 errx(1, "io_loop?");
114         end = time_now();
115
116         for (i = 0; i < NUM; i++) {
117                 char b[sizeof(buf[0].buf)];
118                 memset(b, i, sizeof(b));
119                 sprintf(b, "%i-%i", i, i);
120                 if (memcmp(b, buf[(i + NUM_ITERS) % NUM].buf, sizeof(b)) != 0)
121                         errx(1, "Buffer for %i was '%s' not '%s'",
122                              i, buf[(i + NUM_ITERS) % NUM].buf, b);
123         }
124
125         printf("run-many: %u %u iterations: %llu usec\n",
126                NUM, NUM_ITERS, (long long)time_to_usec(time_sub(end, start)));
127         return 0;
128 }