xref: /netbsd-src/external/bsd/libevent/dist/test/bench_cascade.c (revision 657871a79c9a2060a6255a242fa1a1ef76b56ec6)
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