michael@0: /* michael@0: * Copyright 2003-2007 Niels Provos michael@0: * Copyright 2007-2012 Niels Provos and Nick Mathewson michael@0: * michael@0: * Redistribution and use in source and binary forms, with or without michael@0: * modification, are permitted provided that the following conditions michael@0: * are met: michael@0: * 1. Redistributions of source code must retain the above copyright michael@0: * notice, this list of conditions and the following disclaimer. michael@0: * 2. Redistributions in binary form must reproduce the above copyright michael@0: * notice, this list of conditions and the following disclaimer in the michael@0: * documentation and/or other materials provided with the distribution. michael@0: * 4. The name of the author may not be used to endorse or promote products michael@0: * derived from this software without specific prior written permission. michael@0: * michael@0: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR michael@0: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES michael@0: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. michael@0: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, michael@0: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT michael@0: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF michael@0: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: * michael@0: * michael@0: * Mon 03/10/2003 - Modified by Davide Libenzi michael@0: * michael@0: * Added chain event propagation to improve the sensitivity of michael@0: * the measure respect to the event loop efficency. michael@0: * michael@0: * michael@0: */ michael@0: michael@0: #include "event2/event-config.h" michael@0: michael@0: #include michael@0: #include michael@0: #ifdef _EVENT_HAVE_SYS_TIME_H michael@0: #include michael@0: #endif michael@0: #ifdef WIN32 michael@0: #define WIN32_LEAN_AND_MEAN michael@0: #include michael@0: #else michael@0: #include michael@0: #include michael@0: #include michael@0: #endif michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #ifdef _EVENT_HAVE_UNISTD_H michael@0: #include michael@0: #endif michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: michael@0: static int count, writes, fired; michael@0: static evutil_socket_t *pipes; michael@0: static int num_pipes, num_active, num_writes; michael@0: static struct event *events; michael@0: michael@0: michael@0: static void michael@0: read_cb(evutil_socket_t fd, short which, void *arg) michael@0: { michael@0: ev_intptr_t idx = (ev_intptr_t) arg, widx = idx + 1; michael@0: u_char ch; michael@0: michael@0: count += recv(fd, (char*)&ch, sizeof(ch), 0); michael@0: if (writes) { michael@0: if (widx >= num_pipes) michael@0: widx -= num_pipes; michael@0: send(pipes[2 * widx + 1], "e", 1, 0); michael@0: writes--; michael@0: fired++; michael@0: } michael@0: } michael@0: michael@0: static struct timeval * michael@0: run_once(void) michael@0: { michael@0: evutil_socket_t *cp, space; michael@0: long i; michael@0: static struct timeval ts, te; michael@0: michael@0: for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { michael@0: if (event_initialized(&events[i])) michael@0: event_del(&events[i]); michael@0: event_set(&events[i], cp[0], EV_READ | EV_PERSIST, read_cb, (void *)(ev_intptr_t) i); michael@0: event_add(&events[i], NULL); michael@0: } michael@0: michael@0: event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); michael@0: michael@0: fired = 0; michael@0: space = num_pipes / num_active; michael@0: space = space * 2; michael@0: for (i = 0; i < num_active; i++, fired++) michael@0: send(pipes[i * space + 1], "e", 1, 0); michael@0: michael@0: count = 0; michael@0: writes = num_writes; michael@0: { int xcount = 0; michael@0: evutil_gettimeofday(&ts, NULL); michael@0: do { michael@0: event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); michael@0: xcount++; michael@0: } while (count != fired); michael@0: evutil_gettimeofday(&te, NULL); michael@0: michael@0: if (xcount != count) fprintf(stderr, "Xcount: %d, Rcount: %d\n", xcount, count); michael@0: } michael@0: michael@0: evutil_timersub(&te, &ts, &te); michael@0: michael@0: return (&te); michael@0: } michael@0: michael@0: int michael@0: main(int argc, char **argv) michael@0: { michael@0: #ifndef WIN32 michael@0: struct rlimit rl; michael@0: #endif michael@0: int i, c; michael@0: struct timeval *tv; michael@0: evutil_socket_t *cp; michael@0: michael@0: #ifdef WIN32 michael@0: WSADATA WSAData; michael@0: WSAStartup(0x101, &WSAData); michael@0: #endif michael@0: num_pipes = 100; michael@0: num_active = 1; michael@0: num_writes = num_pipes; michael@0: while ((c = getopt(argc, argv, "n:a:w:")) != -1) { michael@0: switch (c) { michael@0: case 'n': michael@0: num_pipes = atoi(optarg); michael@0: break; michael@0: case 'a': michael@0: num_active = atoi(optarg); michael@0: break; michael@0: case 'w': michael@0: num_writes = atoi(optarg); michael@0: break; michael@0: default: michael@0: fprintf(stderr, "Illegal argument \"%c\"\n", c); michael@0: exit(1); michael@0: } michael@0: } michael@0: michael@0: #ifndef WIN32 michael@0: rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50; michael@0: if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { michael@0: perror("setrlimit"); michael@0: exit(1); michael@0: } michael@0: #endif michael@0: michael@0: events = calloc(num_pipes, sizeof(struct event)); michael@0: pipes = calloc(num_pipes * 2, sizeof(evutil_socket_t)); michael@0: if (events == NULL || pipes == NULL) { michael@0: perror("malloc"); michael@0: exit(1); michael@0: } michael@0: michael@0: event_init(); michael@0: michael@0: for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { michael@0: #ifdef USE_PIPES michael@0: if (pipe(cp) == -1) { michael@0: #else michael@0: if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) { michael@0: #endif michael@0: perror("pipe"); michael@0: exit(1); michael@0: } michael@0: } michael@0: michael@0: for (i = 0; i < 25; i++) { michael@0: tv = run_once(); michael@0: if (tv == NULL) michael@0: exit(1); michael@0: fprintf(stdout, "%ld\n", michael@0: tv->tv_sec * 1000000L + tv->tv_usec); michael@0: } michael@0: michael@0: exit(0); michael@0: }