diff options
Diffstat (limited to 'libevent/test/bench.c')
-rw-r--r-- | libevent/test/bench.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/libevent/test/bench.c b/libevent/test/bench.c new file mode 100644 index 0000000..f2af4d3 --- /dev/null +++ b/libevent/test/bench.c @@ -0,0 +1,235 @@ +/* + * Copyright 2003-2007 Niels Provos <provos@citi.umich.edu> + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Mon 03/10/2003 - Modified by Davide Libenzi <davidel@xmailserver.org> + * + * Added chain event propagation to improve the sensitivity of + * the measure respect to the event loop efficency. + * + * + */ + +#include "event2/event-config.h" +#include "../util-internal.h" + +#include <sys/types.h> +#include <sys/stat.h> +#ifdef EVENT__HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#else +#include <sys/socket.h> +#include <signal.h> +#include <sys/resource.h> +#endif +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#ifdef EVENT__HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <errno.h> + +#ifdef _WIN32 +#include <getopt.h> +#endif + +#include <event.h> +#include <evutil.h> + +static ev_ssize_t count, fired; +static int writes, failures; +static evutil_socket_t *pipes; +static int num_pipes, num_active, num_writes; +static struct event *events; +static struct event_base *base; + + +static void +read_cb(evutil_socket_t fd, short which, void *arg) +{ + ev_intptr_t idx = (ev_intptr_t) arg, widx = idx + 1; + unsigned char ch; + ev_ssize_t n; + + n = recv(fd, (char*)&ch, sizeof(ch), 0); + if (n >= 0) + count += n; + else + failures++; + if (writes) { + if (widx >= num_pipes) + widx -= num_pipes; + n = send(pipes[2 * widx + 1], "e", 1, 0); + if (n != 1) + failures++; + writes--; + fired++; + } +} + +static struct timeval * +run_once(void) +{ + evutil_socket_t *cp, space; + long i; + static struct timeval ts, te; + + for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { + if (event_initialized(&events[i])) + event_del(&events[i]); + event_assign(&events[i], base, cp[0], EV_READ | EV_PERSIST, read_cb, (void *)(ev_intptr_t) i); + event_add(&events[i], NULL); + } + + event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK); + + fired = 0; + space = num_pipes / num_active; + space = space * 2; + for (i = 0; i < num_active; i++, fired++) + (void) send(pipes[i * space + 1], "e", 1, 0); + + count = 0; + writes = num_writes; + { + int xcount = 0; + evutil_gettimeofday(&ts, NULL); + do { + event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK); + xcount++; + } while (count != fired); + evutil_gettimeofday(&te, NULL); + + if (xcount != count) + fprintf(stderr, "Xcount: %d, Rcount: " EV_SSIZE_FMT "\n", + xcount, count); + } + + evutil_timersub(&te, &ts, &te); + + return (&te); +} + +int +main(int argc, char **argv) +{ +#ifdef EVENT__HAVE_SETRLIMIT + struct rlimit rl; +#endif + int i, c; + struct timeval *tv; + evutil_socket_t *cp; + const char **methods; + const char *method = NULL; + struct event_config *cfg = NULL; + +#ifdef _WIN32 + WSADATA WSAData; + WSAStartup(0x101, &WSAData); +#endif + num_pipes = 100; + num_active = 1; + num_writes = num_pipes; + while ((c = getopt(argc, argv, "n:a:w:m:l")) != -1) { + switch (c) { + case 'n': + num_pipes = atoi(optarg); + break; + case 'a': + num_active = atoi(optarg); + break; + case 'w': + num_writes = atoi(optarg); + break; + case 'm': + method = optarg; + break; + case 'l': + methods = event_get_supported_methods(); + fprintf(stdout, "Using Libevent %s. Available methods are:\n", + event_get_version()); + for (i = 0; methods[i] != NULL; ++i) + printf(" %s\n", methods[i]); + exit(0); + default: + fprintf(stderr, "Illegal argument \"%c\"\n", c); + exit(1); + } + } + +#ifdef EVENT__HAVE_SETRLIMIT + rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50; + if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { + perror("setrlimit"); + exit(1); + } +#endif + + events = calloc(num_pipes, sizeof(struct event)); + pipes = calloc(num_pipes * 2, sizeof(evutil_socket_t)); + if (events == NULL || pipes == NULL) { + perror("malloc"); + exit(1); + } + + if (method != NULL) { + cfg = event_config_new(); + methods = event_get_supported_methods(); + for (i = 0; methods[i] != NULL; ++i) + if (strcmp(methods[i], method)) + event_config_avoid_method(cfg, methods[i]); + base = event_base_new_with_config(cfg); + event_config_free(cfg); + } else + base = event_base_new(); + + for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { +#ifdef USE_PIPES + if (pipe(cp) == -1) { +#else + if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) { +#endif + perror("pipe"); + exit(1); + } + } + + for (i = 0; i < 25; i++) { + tv = run_once(); + if (tv == NULL) + exit(1); + fprintf(stdout, "%ld\n", + tv->tv_sec * 1000000L + tv->tv_usec); + } + + exit(0); +} |