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