1 /*
2 * Copyright 2012 William Pitcock <nenolod@dereferenced.org>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright 2003 Niels Provos <provos@citi.umich.edu>
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 4. The name of the author may not be used to endorse or promote products
45 * derived from this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 *
58 *
59 * Mon 03/10/2003 - Modified by Davide Libenzi <davidel@xmailserver.org>
60 *
61 * Added chain event propagation to improve the sensitivity of
62 * the measure respect to the event loop efficency.
63 *
64 *
65 */
66
67 #define timersub(tvp, uvp, vvp) \
68 do \
69 { \
70 (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
71 (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
72 if ((vvp)->tv_usec < 0) \
73 { \
74 (vvp)->tv_sec--; \
75 (vvp)->tv_usec += 1000000; \
76 } \
77 } while (0)
78
79 #include <mowgli.h>
80
81 static int count, writes, fired;
82 static mowgli_eventloop_t *base_eventloop;
83 static mowgli_descriptor_t *pipes;
84 static int num_pipes, num_active, num_writes;
85 static mowgli_eventloop_pollable_t **events;
86 static int timers;
87
88 void
timer_cb(void * unused)89 timer_cb(void *unused)
90 {
91 /* nop */
92 }
93
94 void
read_cb(mowgli_eventloop_t * eventloop,mowgli_eventloop_io_t * io,mowgli_eventloop_io_dir_t dir,void * arg)95 read_cb(mowgli_eventloop_t *eventloop, mowgli_eventloop_io_t *io, mowgli_eventloop_io_dir_t dir, void *arg)
96 {
97 mowgli_eventloop_pollable_t *pollable = mowgli_eventloop_io_pollable(io);
98
99 int idx = (int) (long) arg, widx = idx + 1;
100 u_char ch;
101
102 count += read(pollable->fd, &ch, sizeof(ch));
103
104 if (writes)
105 {
106 if (widx >= num_pipes)
107 widx -= num_pipes;
108
109 write(pipes[2 * widx + 1], "e", 1);
110 writes--;
111 fired++;
112 }
113 }
114
115 #if NATIVE
116 void
read_thunk(struct ev_io * w,int revents)117 read_thunk(struct ev_io *w, int revents)
118 {
119 read_cb(w->fd, revents, w->data);
120 }
121
122 void
timer_cb(struct ev_timer * w,int revents)123 timer_cb(struct ev_timer *w, int revents)
124 {
125 /* nop */
126 }
127
128 #endif
129
130 struct timeval *
run_once(void)131 run_once(void)
132 {
133 int *cp, i, space;
134
135 static struct timeval ta, ts, te;
136
137 gettimeofday(&ta, NULL);
138
139 for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2)
140 {
141 if (events[i] != NULL)
142 mowgli_pollable_destroy(base_eventloop, events[i]);
143
144 events[i] = mowgli_pollable_create(base_eventloop, cp[0], (void *) (long) i);
145 mowgli_pollable_setselect(base_eventloop, events[i], MOWGLI_EVENTLOOP_IO_READ, read_cb);
146 }
147
148 fired = 0;
149 space = num_pipes / num_active;
150 space = space * 2;
151
152 for (i = 0; i < num_active; i++, fired++)
153 write(pipes[i * space + 1], "e", 1);
154
155 count = 0;
156 writes = num_writes;
157
158 int xcount = 0;
159 gettimeofday(&ts, NULL);
160
161 do
162 {
163 mowgli_eventloop_run_once(base_eventloop);
164 xcount++;
165 } while (count != fired);
166
167 gettimeofday(&te, NULL);
168
169 timersub(&te, &ta, &ta);
170 timersub(&te, &ts, &ts);
171 fprintf(stdout, "%ld\t%ld\n",
172 ta.tv_sec * 1000000L + ta.tv_usec,
173 ts.tv_sec * 1000000L + ts.tv_usec
174 );
175
176 return &te;
177 }
178
179 int
main(int argc,char ** argv)180 main(int argc, char **argv)
181 {
182 struct rlimit rl;
183
184 int i, c;
185 int *cp;
186 extern char *optarg;
187
188 num_pipes = 100;
189 num_active = 1;
190 num_writes = num_pipes;
191
192 while ((c = getopt(argc, argv, "n:a:w:te")) != -1)
193 {
194 switch (c)
195 {
196 case 'n':
197 num_pipes = atoi(optarg);
198 break;
199 case 'a':
200 num_active = atoi(optarg);
201 break;
202 case 'w':
203 num_writes = atoi(optarg);
204 break;
205 case 't':
206 timers = 1;
207 break;
208 default:
209 fprintf(stderr, "Illegal argument \"%c\"\n", c);
210 exit(1);
211 }
212 }
213
214 #if 1
215 rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
216
217 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
218 perror("setrlimit");
219
220 #endif
221
222 events = calloc(num_pipes * 2, sizeof(mowgli_eventloop_pollable_t *));
223 pipes = calloc(num_pipes * 2, sizeof(mowgli_descriptor_t));
224
225 if ((events == NULL) || (pipes == NULL))
226 {
227 perror("malloc");
228 exit(1);
229 }
230
231 mowgli_thread_set_policy(MOWGLI_THREAD_POLICY_DISABLED);
232 base_eventloop = mowgli_eventloop_create();
233
234 for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2)
235 {
236 #ifdef USE_PIPES
237
238 if (pipe(cp) == -1)
239 {
240 #else
241
242 if (socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1)
243 {
244 #endif
245 perror("pipe");
246 exit(1);
247 }
248 }
249
250 for (i = 0; i < 2; i++)
251 run_once();
252
253 exit(0);
254 }
255