tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

bench.c (5844B)


      1 /*
      2 * Copyright 2003-2007 Niels Provos <provos@citi.umich.edu>
      3 * Copyright 2007-2012 Niels Provos and Nick Mathewson
      4 *
      5 * Redistribution and use in source and binary forms, with or without
      6 * modification, are permitted provided that the following conditions
      7 * are met:
      8 * 1. Redistributions of source code must retain the above copyright
      9 *    notice, this list of conditions and the following disclaimer.
     10 * 2. Redistributions in binary form must reproduce the above copyright
     11 *    notice, this list of conditions and the following disclaimer in the
     12 *    documentation and/or other materials provided with the distribution.
     13 * 4. The name of the author may not be used to endorse or promote products
     14 *    derived from this software without specific prior written permission.
     15 *
     16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 *
     27 *
     28 * Mon 03/10/2003 - Modified by Davide Libenzi <davidel@xmailserver.org>
     29 *
     30 *     Added chain event propagation to improve the sensitivity of
     31 *     the measure respect to the event loop efficency.
     32 *
     33 *
     34 */
     35 
     36 #include "event2/event-config.h"
     37 #include "../util-internal.h"
     38 
     39 #include <sys/types.h>
     40 #include <sys/stat.h>
     41 #ifdef EVENT__HAVE_SYS_TIME_H
     42 #include <sys/time.h>
     43 #endif
     44 #ifdef _WIN32
     45 #define WIN32_LEAN_AND_MEAN
     46 #include <windows.h>
     47 #else
     48 #include <sys/socket.h>
     49 #include <signal.h>
     50 #include <sys/resource.h>
     51 #endif
     52 #include <fcntl.h>
     53 #include <stdlib.h>
     54 #include <stdio.h>
     55 #include <string.h>
     56 #ifdef EVENT__HAVE_UNISTD_H
     57 #include <unistd.h>
     58 #endif
     59 #include <errno.h>
     60 
     61 #ifdef _WIN32
     62 #include <getopt.h>
     63 #endif
     64 
     65 #include <event.h>
     66 #include <evutil.h>
     67 
     68 static ev_ssize_t count, fired;
     69 static int writes, failures;
     70 static evutil_socket_t *pipes;
     71 static int num_pipes, num_active, num_writes;
     72 static struct event *events;
     73 static struct event_base *base;
     74 
     75 
     76 static void
     77 read_cb(evutil_socket_t fd, short which, void *arg)
     78 {
     79 ev_intptr_t idx = (ev_intptr_t) arg, widx = idx + 1;
     80 unsigned char ch;
     81 ev_ssize_t n;
     82 
     83 n = recv(fd, (char*)&ch, sizeof(ch), 0);
     84 if (n >= 0)
     85 	count += n;
     86 else
     87 	failures++;
     88 if (writes) {
     89 	if (widx >= num_pipes)
     90 		widx -= num_pipes;
     91 	n = send(pipes[2 * widx + 1], "e", 1, 0);
     92 	if (n != 1)
     93 		failures++;
     94 	writes--;
     95 	fired++;
     96 }
     97 }
     98 
     99 static struct timeval *
    100 run_once(void)
    101 {
    102 evutil_socket_t *cp, space;
    103 long i;
    104 static struct timeval ts, te;
    105 
    106 for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
    107 	if (event_initialized(&events[i]))
    108 		event_del(&events[i]);
    109 	event_assign(&events[i], base, cp[0], EV_READ | EV_PERSIST, read_cb, (void *)(ev_intptr_t) i);
    110 	event_add(&events[i], NULL);
    111 }
    112 
    113 event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK);
    114 
    115 fired = 0;
    116 space = num_pipes / num_active;
    117 space = space * 2;
    118 for (i = 0; i < num_active; i++, fired++)
    119 	(void) send(pipes[i * space + 1], "e", 1, 0);
    120 
    121 count = 0;
    122 writes = num_writes;
    123 {
    124 	int xcount = 0;
    125 	evutil_gettimeofday(&ts, NULL);
    126 	do {
    127 		event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK);
    128 		xcount++;
    129 	} while (count != fired);
    130 	evutil_gettimeofday(&te, NULL);
    131 
    132 	if (xcount != count)
    133 		fprintf(stderr, "Xcount: %d, Rcount: " EV_SSIZE_FMT "\n",
    134 			xcount, count);
    135 }
    136 
    137 evutil_timersub(&te, &ts, &te);
    138 
    139 return (&te);
    140 }
    141 
    142 int
    143 main(int argc, char **argv)
    144 {
    145 #ifdef EVENT__HAVE_SETRLIMIT
    146 struct rlimit rl;
    147 #endif
    148 int i, c;
    149 struct timeval *tv;
    150 evutil_socket_t *cp;
    151 const char **methods;
    152 const char *method = NULL;
    153 struct event_config *cfg = NULL;
    154 
    155 #ifdef _WIN32
    156 WSADATA WSAData;
    157 WSAStartup(0x101, &WSAData);
    158 #endif
    159 num_pipes = 100;
    160 num_active = 1;
    161 num_writes = num_pipes;
    162 while ((c = getopt(argc, argv, "n:a:w:m:l")) != -1) {
    163 	switch (c) {
    164 	case 'n':
    165 		num_pipes = atoi(optarg);
    166 		break;
    167 	case 'a':
    168 		num_active = atoi(optarg);
    169 		break;
    170 	case 'w':
    171 		num_writes = atoi(optarg);
    172 		break;
    173 	case 'm':
    174 		method = optarg;
    175 		break;
    176 	case 'l':
    177 		methods = event_get_supported_methods();
    178 		fprintf(stdout, "Using Libevent %s. Available methods are:\n",
    179 			event_get_version());
    180 		for (i = 0; methods[i] != NULL; ++i)
    181 			printf("    %s\n", methods[i]);
    182 		exit(0);
    183 	default:
    184 		fprintf(stderr, "Illegal argument \"%c\"\n", c);
    185 		exit(1);
    186 	}
    187 }
    188 
    189 #ifdef EVENT__HAVE_SETRLIMIT
    190 rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
    191 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
    192 	perror("setrlimit");
    193 	exit(1);
    194 }
    195 #endif
    196 
    197 events = calloc(num_pipes, sizeof(struct event));
    198 pipes = calloc(num_pipes * 2, sizeof(evutil_socket_t));
    199 if (events == NULL || pipes == NULL) {
    200 	perror("malloc");
    201 	exit(1);
    202 }
    203 
    204 if (method != NULL) {
    205 	cfg = event_config_new();
    206 	methods = event_get_supported_methods();
    207 	for (i = 0; methods[i] != NULL; ++i)
    208 		if (strcmp(methods[i], method))
    209 			event_config_avoid_method(cfg, methods[i]);
    210 	base = event_base_new_with_config(cfg);
    211 	event_config_free(cfg);
    212 } else
    213 	base = event_base_new();
    214 
    215 for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
    216 #ifdef USE_PIPES
    217 	if (pipe(cp) == -1) {
    218 #else
    219 	if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) {
    220 #endif
    221 		perror("pipe");
    222 		exit(1);
    223 	}
    224 }
    225 
    226 for (i = 0; i < 25; i++) {
    227 	tv = run_once();
    228 	if (tv == NULL)
    229 		exit(1);
    230 	fprintf(stdout, "%ld\n",
    231 		tv->tv_sec * 1000000L + tv->tv_usec);
    232 }
    233 
    234 exit(0);
    235 }