1*657871a7Schristos /* $NetBSD: bench_cascade.c,v 1.1.1.3 2021/04/07 02:43:15 christos Exp $ */
26ecf6635Schristos /*
36ecf6635Schristos * Copyright 2007-2012 Niels Provos and Nick Mathewson
46ecf6635Schristos *
56ecf6635Schristos * Redistribution and use in source and binary forms, with or without
66ecf6635Schristos * modification, are permitted provided that the following conditions
76ecf6635Schristos * are met:
86ecf6635Schristos * 1. Redistributions of source code must retain the above copyright
96ecf6635Schristos * notice, this list of conditions and the following disclaimer.
106ecf6635Schristos * 2. Redistributions in binary form must reproduce the above copyright
116ecf6635Schristos * notice, this list of conditions and the following disclaimer in the
126ecf6635Schristos * documentation and/or other materials provided with the distribution.
136ecf6635Schristos * 4. The name of the author may not be used to endorse or promote products
146ecf6635Schristos * derived from this software without specific prior written permission.
156ecf6635Schristos *
166ecf6635Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
176ecf6635Schristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
186ecf6635Schristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
196ecf6635Schristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
206ecf6635Schristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
216ecf6635Schristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
226ecf6635Schristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
236ecf6635Schristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
246ecf6635Schristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
256ecf6635Schristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
266ecf6635Schristos *
276ecf6635Schristos */
286ecf6635Schristos
296ecf6635Schristos #include "event2/event-config.h"
306ecf6635Schristos #include <sys/cdefs.h>
31*657871a7Schristos __RCSID("$NetBSD: bench_cascade.c,v 1.1.1.3 2021/04/07 02:43:15 christos Exp $");
326ecf6635Schristos
336ecf6635Schristos #include <sys/types.h>
346ecf6635Schristos #include <sys/stat.h>
35805a1ce9Schristos #ifdef EVENT__HAVE_SYS_TIME_H
366ecf6635Schristos #include <sys/time.h>
376ecf6635Schristos #endif
38805a1ce9Schristos #ifdef _WIN32
396ecf6635Schristos #define WIN32_LEAN_AND_MEAN
406ecf6635Schristos #include <windows.h>
41*657871a7Schristos #include <getopt.h>
42*657871a7Schristos #else /* _WIN32 */
436ecf6635Schristos #include <sys/socket.h>
446ecf6635Schristos #include <sys/resource.h>
456ecf6635Schristos #endif
466ecf6635Schristos #include <signal.h>
476ecf6635Schristos #include <fcntl.h>
486ecf6635Schristos #include <stdlib.h>
496ecf6635Schristos #include <stdio.h>
506ecf6635Schristos #include <string.h>
51805a1ce9Schristos #ifdef EVENT__HAVE_UNISTD_H
526ecf6635Schristos #include <unistd.h>
536ecf6635Schristos #endif
546ecf6635Schristos #include <errno.h>
556ecf6635Schristos #include <event.h>
566ecf6635Schristos #include <evutil.h>
576ecf6635Schristos
586ecf6635Schristos /*
596ecf6635Schristos * This benchmark tests how quickly we can propagate a write down a chain
606ecf6635Schristos * of socket pairs. We start by writing to the first socket pair and all
616ecf6635Schristos * events will fire subsequently until the last socket pair has been reached
626ecf6635Schristos * and the benchmark terminates.
636ecf6635Schristos */
646ecf6635Schristos
656ecf6635Schristos static int fired;
666ecf6635Schristos static evutil_socket_t *pipes;
676ecf6635Schristos static struct event *events;
686ecf6635Schristos
696ecf6635Schristos static void
read_cb(evutil_socket_t fd,short which,void * arg)706ecf6635Schristos read_cb(evutil_socket_t fd, short which, void *arg)
716ecf6635Schristos {
726ecf6635Schristos char ch;
736ecf6635Schristos evutil_socket_t sock = (evutil_socket_t)(ev_intptr_t)arg;
746ecf6635Schristos
75805a1ce9Schristos (void) recv(fd, &ch, sizeof(ch), 0);
766ecf6635Schristos if (sock >= 0) {
776ecf6635Schristos if (send(sock, "e", 1, 0) < 0)
786ecf6635Schristos perror("send");
796ecf6635Schristos }
806ecf6635Schristos fired++;
816ecf6635Schristos }
826ecf6635Schristos
836ecf6635Schristos static struct timeval *
run_once(int num_pipes)846ecf6635Schristos run_once(int num_pipes)
856ecf6635Schristos {
866ecf6635Schristos int i;
876ecf6635Schristos evutil_socket_t *cp;
886ecf6635Schristos static struct timeval ts, te, tv_timeout;
896ecf6635Schristos
90805a1ce9Schristos events = (struct event *)calloc(num_pipes, sizeof(struct event));
91805a1ce9Schristos pipes = (evutil_socket_t *)calloc(num_pipes * 2, sizeof(evutil_socket_t));
926ecf6635Schristos
936ecf6635Schristos if (events == NULL || pipes == NULL) {
946ecf6635Schristos perror("malloc");
956ecf6635Schristos exit(1);
966ecf6635Schristos }
976ecf6635Schristos
986ecf6635Schristos for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
996ecf6635Schristos if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) {
1006ecf6635Schristos perror("socketpair");
1016ecf6635Schristos exit(1);
1026ecf6635Schristos }
1036ecf6635Schristos }
1046ecf6635Schristos
1056ecf6635Schristos /* measurements includes event setup */
1066ecf6635Schristos evutil_gettimeofday(&ts, NULL);
1076ecf6635Schristos
1086ecf6635Schristos /* provide a default timeout for events */
1096ecf6635Schristos evutil_timerclear(&tv_timeout);
1106ecf6635Schristos tv_timeout.tv_sec = 60;
1116ecf6635Schristos
1126ecf6635Schristos for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
1136ecf6635Schristos evutil_socket_t fd = i < num_pipes - 1 ? cp[3] : -1;
1146ecf6635Schristos event_set(&events[i], cp[0], EV_READ, read_cb,
1156ecf6635Schristos (void *)(ev_intptr_t)fd);
1166ecf6635Schristos event_add(&events[i], &tv_timeout);
1176ecf6635Schristos }
1186ecf6635Schristos
1196ecf6635Schristos fired = 0;
1206ecf6635Schristos
1216ecf6635Schristos /* kick everything off with a single write */
1226ecf6635Schristos if (send(pipes[1], "e", 1, 0) < 0)
1236ecf6635Schristos perror("send");
1246ecf6635Schristos
1256ecf6635Schristos event_dispatch();
1266ecf6635Schristos
1276ecf6635Schristos evutil_gettimeofday(&te, NULL);
1286ecf6635Schristos evutil_timersub(&te, &ts, &te);
1296ecf6635Schristos
1306ecf6635Schristos for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
1316ecf6635Schristos event_del(&events[i]);
132805a1ce9Schristos evutil_closesocket(cp[0]);
133805a1ce9Schristos evutil_closesocket(cp[1]);
1346ecf6635Schristos }
1356ecf6635Schristos
1366ecf6635Schristos free(pipes);
1376ecf6635Schristos free(events);
1386ecf6635Schristos
1396ecf6635Schristos return (&te);
1406ecf6635Schristos }
1416ecf6635Schristos
1426ecf6635Schristos int
main(int argc,char ** argv)1436ecf6635Schristos main(int argc, char **argv)
1446ecf6635Schristos {
145*657871a7Schristos #ifdef EVENT__HAVE_SETRLIMIT
1466ecf6635Schristos struct rlimit rl;
1476ecf6635Schristos #endif
1486ecf6635Schristos int i, c;
1496ecf6635Schristos struct timeval *tv;
1506ecf6635Schristos
1516ecf6635Schristos int num_pipes = 100;
152805a1ce9Schristos #ifdef _WIN32
153805a1ce9Schristos WSADATA WSAData;
154805a1ce9Schristos WSAStartup(0x101, &WSAData);
155805a1ce9Schristos #endif
156805a1ce9Schristos
1576ecf6635Schristos while ((c = getopt(argc, argv, "n:")) != -1) {
1586ecf6635Schristos switch (c) {
1596ecf6635Schristos case 'n':
1606ecf6635Schristos num_pipes = atoi(optarg);
1616ecf6635Schristos break;
1626ecf6635Schristos default:
1636ecf6635Schristos fprintf(stderr, "Illegal argument \"%c\"\n", c);
1646ecf6635Schristos exit(1);
1656ecf6635Schristos }
1666ecf6635Schristos }
1676ecf6635Schristos
168*657871a7Schristos #ifdef EVENT__HAVE_SETRLIMIT
1696ecf6635Schristos rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
1706ecf6635Schristos if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
1716ecf6635Schristos perror("setrlimit");
1726ecf6635Schristos exit(1);
1736ecf6635Schristos }
1746ecf6635Schristos #endif
1756ecf6635Schristos
1766ecf6635Schristos event_init();
1776ecf6635Schristos
1786ecf6635Schristos for (i = 0; i < 25; i++) {
1796ecf6635Schristos tv = run_once(num_pipes);
1806ecf6635Schristos if (tv == NULL)
1816ecf6635Schristos exit(1);
1826ecf6635Schristos fprintf(stdout, "%ld\n",
1836ecf6635Schristos tv->tv_sec * 1000000L + tv->tv_usec);
1846ecf6635Schristos }
1856ecf6635Schristos
186805a1ce9Schristos #ifdef _WIN32
187805a1ce9Schristos WSACleanup();
188805a1ce9Schristos #endif
189805a1ce9Schristos
1906ecf6635Schristos exit(0);
1916ecf6635Schristos }
192