1*eabc0478Schristos /* $NetBSD: bench.c,v 1.6 2024/08/18 20:47:23 christos Exp $ */ 28585484eSchristos 38585484eSchristos /* 48585484eSchristos * Copyright 2003-2007 Niels Provos <provos@citi.umich.edu> 58585484eSchristos * Copyright 2007-2012 Niels Provos and Nick Mathewson 68585484eSchristos * 78585484eSchristos * Redistribution and use in source and binary forms, with or without 88585484eSchristos * modification, are permitted provided that the following conditions 98585484eSchristos * are met: 108585484eSchristos * 1. Redistributions of source code must retain the above copyright 118585484eSchristos * notice, this list of conditions and the following disclaimer. 128585484eSchristos * 2. Redistributions in binary form must reproduce the above copyright 138585484eSchristos * notice, this list of conditions and the following disclaimer in the 148585484eSchristos * documentation and/or other materials provided with the distribution. 158585484eSchristos * 4. The name of the author may not be used to endorse or promote products 168585484eSchristos * derived from this software without specific prior written permission. 178585484eSchristos * 188585484eSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 198585484eSchristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 208585484eSchristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 218585484eSchristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 228585484eSchristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 238585484eSchristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 248585484eSchristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 258585484eSchristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 268585484eSchristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 278585484eSchristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 288585484eSchristos * 298585484eSchristos * 308585484eSchristos * Mon 03/10/2003 - Modified by Davide Libenzi <davidel@xmailserver.org> 318585484eSchristos * 328585484eSchristos * Added chain event propagation to improve the sensitivity of 338585484eSchristos * the measure respect to the event loop efficency. 348585484eSchristos * 358585484eSchristos * 368585484eSchristos */ 378585484eSchristos 388585484eSchristos #include "event2/event-config.h" 39*eabc0478Schristos #include "../util-internal.h" 408585484eSchristos 418585484eSchristos #include <sys/types.h> 428585484eSchristos #include <sys/stat.h> 438585484eSchristos #ifdef EVENT__HAVE_SYS_TIME_H 448585484eSchristos #include <sys/time.h> 458585484eSchristos #endif 468585484eSchristos #ifdef _WIN32 478585484eSchristos #define WIN32_LEAN_AND_MEAN 488585484eSchristos #include <windows.h> 498585484eSchristos #else 508585484eSchristos #include <sys/socket.h> 518585484eSchristos #include <signal.h> 528585484eSchristos #include <sys/resource.h> 538585484eSchristos #endif 548585484eSchristos #include <fcntl.h> 558585484eSchristos #include <stdlib.h> 568585484eSchristos #include <stdio.h> 578585484eSchristos #include <string.h> 588585484eSchristos #ifdef EVENT__HAVE_UNISTD_H 598585484eSchristos #include <unistd.h> 608585484eSchristos #endif 618585484eSchristos #include <errno.h> 628585484eSchristos 63b8ecfcfeSchristos #ifdef _WIN32 64b8ecfcfeSchristos #include <getopt.h> 65b8ecfcfeSchristos #endif 66b8ecfcfeSchristos 678585484eSchristos #include <event.h> 688585484eSchristos #include <evutil.h> 698585484eSchristos 70*eabc0478Schristos static ev_ssize_t count, fired; 71*eabc0478Schristos static int writes, failures; 728585484eSchristos static evutil_socket_t *pipes; 738585484eSchristos static int num_pipes, num_active, num_writes; 748585484eSchristos static struct event *events; 75*eabc0478Schristos static struct event_base *base; 768585484eSchristos 778585484eSchristos 788585484eSchristos static void 798585484eSchristos read_cb(evutil_socket_t fd, short which, void *arg) 808585484eSchristos { 818585484eSchristos ev_intptr_t idx = (ev_intptr_t) arg, widx = idx + 1; 82*eabc0478Schristos unsigned char ch; 83b8ecfcfeSchristos ev_ssize_t n; 848585484eSchristos 85b8ecfcfeSchristos n = recv(fd, (char*)&ch, sizeof(ch), 0); 86b8ecfcfeSchristos if (n >= 0) 87b8ecfcfeSchristos count += n; 88b8ecfcfeSchristos else 89b8ecfcfeSchristos failures++; 908585484eSchristos if (writes) { 918585484eSchristos if (widx >= num_pipes) 928585484eSchristos widx -= num_pipes; 93b8ecfcfeSchristos n = send(pipes[2 * widx + 1], "e", 1, 0); 94b8ecfcfeSchristos if (n != 1) 95b8ecfcfeSchristos failures++; 968585484eSchristos writes--; 978585484eSchristos fired++; 988585484eSchristos } 998585484eSchristos } 1008585484eSchristos 1018585484eSchristos static struct timeval * 1028585484eSchristos run_once(void) 1038585484eSchristos { 1048585484eSchristos evutil_socket_t *cp, space; 1058585484eSchristos long i; 1068585484eSchristos static struct timeval ts, te; 1078585484eSchristos 1088585484eSchristos for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { 1098585484eSchristos if (event_initialized(&events[i])) 1108585484eSchristos event_del(&events[i]); 111*eabc0478Schristos event_assign(&events[i], base, cp[0], EV_READ | EV_PERSIST, read_cb, (void *)(ev_intptr_t) i); 1128585484eSchristos event_add(&events[i], NULL); 1138585484eSchristos } 1148585484eSchristos 115*eabc0478Schristos event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK); 1168585484eSchristos 1178585484eSchristos fired = 0; 1188585484eSchristos space = num_pipes / num_active; 1198585484eSchristos space = space * 2; 1208585484eSchristos for (i = 0; i < num_active; i++, fired++) 121b8ecfcfeSchristos (void) send(pipes[i * space + 1], "e", 1, 0); 1228585484eSchristos 1238585484eSchristos count = 0; 1248585484eSchristos writes = num_writes; 125*eabc0478Schristos { 126*eabc0478Schristos int xcount = 0; 1278585484eSchristos evutil_gettimeofday(&ts, NULL); 1288585484eSchristos do { 129*eabc0478Schristos event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK); 1308585484eSchristos xcount++; 1318585484eSchristos } while (count != fired); 1328585484eSchristos evutil_gettimeofday(&te, NULL); 1338585484eSchristos 134*eabc0478Schristos if (xcount != count) 135*eabc0478Schristos fprintf(stderr, "Xcount: %d, Rcount: " EV_SSIZE_FMT "\n", 136*eabc0478Schristos xcount, count); 1378585484eSchristos } 1388585484eSchristos 1398585484eSchristos evutil_timersub(&te, &ts, &te); 1408585484eSchristos 1418585484eSchristos return (&te); 1428585484eSchristos } 1438585484eSchristos 1448585484eSchristos int 1458585484eSchristos main(int argc, char **argv) 1468585484eSchristos { 147*eabc0478Schristos #ifdef EVENT__HAVE_SETRLIMIT 1488585484eSchristos struct rlimit rl; 1498585484eSchristos #endif 1508585484eSchristos int i, c; 1518585484eSchristos struct timeval *tv; 1528585484eSchristos evutil_socket_t *cp; 153*eabc0478Schristos const char **methods; 154*eabc0478Schristos const char *method = NULL; 155*eabc0478Schristos struct event_config *cfg = NULL; 1568585484eSchristos 1578585484eSchristos #ifdef _WIN32 1588585484eSchristos WSADATA WSAData; 1598585484eSchristos WSAStartup(0x101, &WSAData); 1608585484eSchristos #endif 1618585484eSchristos num_pipes = 100; 1628585484eSchristos num_active = 1; 1638585484eSchristos num_writes = num_pipes; 164*eabc0478Schristos while ((c = getopt(argc, argv, "n:a:w:m:l")) != -1) { 1658585484eSchristos switch (c) { 1668585484eSchristos case 'n': 1678585484eSchristos num_pipes = atoi(optarg); 1688585484eSchristos break; 1698585484eSchristos case 'a': 1708585484eSchristos num_active = atoi(optarg); 1718585484eSchristos break; 1728585484eSchristos case 'w': 1738585484eSchristos num_writes = atoi(optarg); 1748585484eSchristos break; 175*eabc0478Schristos case 'm': 176*eabc0478Schristos method = optarg; 177*eabc0478Schristos break; 178*eabc0478Schristos case 'l': 179*eabc0478Schristos methods = event_get_supported_methods(); 180*eabc0478Schristos fprintf(stdout, "Using Libevent %s. Available methods are:\n", 181*eabc0478Schristos event_get_version()); 182*eabc0478Schristos for (i = 0; methods[i] != NULL; ++i) 183*eabc0478Schristos printf(" %s\n", methods[i]); 184*eabc0478Schristos exit(0); 1858585484eSchristos default: 1868585484eSchristos fprintf(stderr, "Illegal argument \"%c\"\n", c); 1878585484eSchristos exit(1); 1888585484eSchristos } 1898585484eSchristos } 1908585484eSchristos 191*eabc0478Schristos #ifdef EVENT__HAVE_SETRLIMIT 1928585484eSchristos rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50; 1938585484eSchristos if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { 1948585484eSchristos perror("setrlimit"); 1958585484eSchristos exit(1); 1968585484eSchristos } 1978585484eSchristos #endif 1988585484eSchristos 1998585484eSchristos events = calloc(num_pipes, sizeof(struct event)); 2008585484eSchristos pipes = calloc(num_pipes * 2, sizeof(evutil_socket_t)); 2018585484eSchristos if (events == NULL || pipes == NULL) { 2028585484eSchristos perror("malloc"); 2038585484eSchristos exit(1); 2048585484eSchristos } 2058585484eSchristos 206*eabc0478Schristos if (method != NULL) { 207*eabc0478Schristos cfg = event_config_new(); 208*eabc0478Schristos methods = event_get_supported_methods(); 209*eabc0478Schristos for (i = 0; methods[i] != NULL; ++i) 210*eabc0478Schristos if (strcmp(methods[i], method)) 211*eabc0478Schristos event_config_avoid_method(cfg, methods[i]); 212*eabc0478Schristos base = event_base_new_with_config(cfg); 213*eabc0478Schristos event_config_free(cfg); 214*eabc0478Schristos } else 215*eabc0478Schristos base = event_base_new(); 2168585484eSchristos 2178585484eSchristos for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { 2188585484eSchristos #ifdef USE_PIPES 2198585484eSchristos if (pipe(cp) == -1) { 2208585484eSchristos #else 2218585484eSchristos if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) { 2228585484eSchristos #endif 2238585484eSchristos perror("pipe"); 2248585484eSchristos exit(1); 2258585484eSchristos } 2268585484eSchristos } 2278585484eSchristos 2288585484eSchristos for (i = 0; i < 25; i++) { 2298585484eSchristos tv = run_once(); 2308585484eSchristos if (tv == NULL) 2318585484eSchristos exit(1); 2328585484eSchristos fprintf(stdout, "%ld\n", 2338585484eSchristos tv->tv_sec * 1000000L + tv->tv_usec); 2348585484eSchristos } 2358585484eSchristos 2368585484eSchristos exit(0); 2378585484eSchristos } 238