Home | History | Annotate | Line # | Download | only in nameibench
      1 /*	$NetBSD: nameibench.c,v 1.3 2019/11/23 20:37:49 ad Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Andrew Doran.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/param.h>
     33 
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include <unistd.h>
     37 #include <string.h>
     38 #include <time.h>
     39 #include <pthread.h>
     40 #include <inttypes.h>
     41 #include <signal.h>
     42 
     43 #define	MAXFILES	4096
     44 
     45 const int primes[] = {
     46 	233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
     47 	293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359,
     48 	367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
     49 	433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491,
     50 	499, 503, 509, 521, 523, 541,
     51 };
     52 
     53 char	**sa;
     54 u_int	sasize;
     55 u_int	sacnt;
     56 struct	timespec sts;
     57 struct	timespec ets;
     58 pthread_barrier_t	barrier;
     59 pthread_mutex_t	lock;
     60 volatile sig_atomic_t	stop;
     61 double	nlookups;
     62 double	ideal;
     63 
     64 static void
     65 makelist(void)
     66 {
     67 	char buf[MAXPATHLEN], *p;
     68 	size_t l;
     69 	FILE *fp;
     70 
     71 	fp = popen("/usr/bin/locate x", "r");
     72 	if (fp == NULL) {
     73 		perror("popen");
     74 		exit(EXIT_FAILURE);
     75 	}
     76 
     77 	while (fgets(buf, sizeof(buf), fp) != NULL) {
     78 		l = strlen(buf) + 1;
     79 		p = malloc(l);
     80 		if (p == NULL) {
     81 			perror("malloc");
     82 			exit(EXIT_FAILURE);
     83 		}
     84 		strcpy(p, buf);
     85 		p[l - 2] = '\0';
     86 		if (sacnt == sasize) {
     87 			sasize += 256;
     88 			sa = realloc(sa, sizeof(*sa) * sasize);
     89 			if (sa == NULL) {
     90 				perror("realloc");
     91 				exit(EXIT_FAILURE);
     92 			}
     93 		}
     94 		sa[sacnt++] = p;
     95 		if (sacnt == MAXFILES) {
     96 			break;
     97 		}
     98 	}
     99 
    100 	fclose(fp);
    101 }
    102 
    103 static void
    104 lookups(int idx)
    105 {
    106 	u_int p, c;
    107 
    108 	for (c = 0, p = 0; !stop; c++) {
    109 		p += primes[idx];
    110 		if (p >= sacnt) {
    111 			p %= sacnt;
    112 		}
    113 		(void)access(sa[p], F_OK);
    114 
    115 	}
    116 
    117 	pthread_mutex_lock(&lock);
    118 	nlookups += c;
    119 	pthread_mutex_unlock(&lock);
    120 }
    121 
    122 static void
    123 start(void)
    124 {
    125 
    126 	(void)pthread_barrier_wait(&barrier);
    127 	if (clock_gettime(CLOCK_MONOTONIC, &sts)) {
    128 		perror("clock_gettime");
    129 		exit(EXIT_FAILURE);
    130 	}
    131 }
    132 
    133 static void
    134 end(void)
    135 {
    136 
    137 	if (clock_gettime(CLOCK_MONOTONIC, &ets)) {
    138 		perror("clock_gettime");
    139 		exit(EXIT_FAILURE);
    140 	}
    141 	(void)pthread_barrier_wait(&barrier);
    142 }
    143 
    144 static void *
    145 thread(void *cookie)
    146 {
    147 
    148 	start();
    149 	lookups((int)(uintptr_t)cookie);
    150 	end();
    151 
    152 	return NULL;
    153 }
    154 
    155 static void
    156 sigalrm(int junk)
    157 {
    158 
    159 	stop = (sig_atomic_t)1;
    160 }
    161 
    162 static void
    163 run(int nt)
    164 {
    165 	pthread_t pt;
    166 	double c;
    167 	int i;
    168 	long us;
    169 
    170 	if (pthread_barrier_init(&barrier, NULL, nt + 1)) {
    171 		fprintf(stderr, "pthread_barrier_init\n");
    172 		exit(EXIT_FAILURE);
    173 	}
    174 
    175 	nlookups = 0;
    176 	stop = 0;
    177 	for (i = 0; i < nt; i++) {
    178 		if (pthread_create(&pt, NULL, thread, (void *)(uintptr_t)i)) {
    179 			fprintf(stderr, "pthread_create\n");
    180 			exit(EXIT_FAILURE);
    181 		}
    182 	}
    183 	start();
    184 	alarm(10);
    185 	end();
    186 	us = (long)(ets.tv_sec * (uint64_t)1000000 + ets.tv_nsec / 1000);
    187 	us -= (long)(sts.tv_sec * (uint64_t)1000000 + sts.tv_nsec / 1000);
    188 	c = nlookups * 1000000.0 / us;
    189 	if (ideal == 0) {
    190 		ideal = c;
    191 	}
    192 	printf("%d\t%d\t%.0f\t%.0f\n", sacnt, nt, c, ideal * nt);
    193 
    194 	if (pthread_barrier_destroy(&barrier)) {
    195 		fprintf(stderr, "pthread_barrier_destroy\n");
    196 		exit(EXIT_FAILURE);
    197 	}
    198 }
    199 
    200 int
    201 main(int argc, char **argv)
    202 {
    203 	int i, mt;
    204 
    205 	(void)setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
    206 	if (argc < 2) {
    207 		mt = sysconf(_SC_NPROCESSORS_ONLN);
    208 	} else {
    209 		mt = atoi(argv[1]);
    210 		if (mt < 1) {
    211 			mt = 1;
    212 		}
    213 	}
    214 	if (pthread_mutex_init(&lock, NULL)) {
    215 		fprintf(stderr, "pthread_mutex_init\n");
    216 		exit(EXIT_FAILURE);
    217 	}
    218 	makelist();
    219 	(void)signal(SIGALRM, sigalrm);
    220 	printf("# nname\tnthr\tpersec\tideal\n");
    221 	for (i = 1; i <= mt; i++) {
    222 		run(i);
    223 	}
    224 	exit(EXIT_SUCCESS);
    225 }
    226