1 /* $NetBSD: nameibench.c,v 1.1 2009/01/29 21:24:19 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 int sasize; 55 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 unsigned 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