11.3Sad/*	$NetBSD: nameibench.c,v 1.3 2019/11/23 20:37:49 ad Exp $	*/
21.1Sad
31.1Sad/*-
41.1Sad * Copyright (c) 2009 The NetBSD Foundation, Inc.
51.1Sad * All rights reserved.
61.1Sad *
71.1Sad * This code is derived from software contributed to The NetBSD Foundation
81.1Sad * by Andrew Doran.
91.1Sad *
101.1Sad * Redistribution and use in source and binary forms, with or without
111.1Sad * modification, are permitted provided that the following conditions
121.1Sad * are met:
131.1Sad * 1. Redistributions of source code must retain the above copyright
141.1Sad *    notice, this list of conditions and the following disclaimer.
151.1Sad * 2. Redistributions in binary form must reproduce the above copyright
161.1Sad *    notice, this list of conditions and the following disclaimer in the
171.1Sad *    documentation and/or other materials provided with the distribution.
181.1Sad *
191.1Sad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201.1Sad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211.1Sad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221.1Sad * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231.1Sad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241.1Sad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251.1Sad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261.1Sad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271.1Sad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281.1Sad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291.1Sad * POSSIBILITY OF SUCH DAMAGE.
301.1Sad */
311.1Sad
321.1Sad#include <sys/param.h>
331.1Sad
341.1Sad#include <stdio.h>
351.1Sad#include <stdlib.h>
361.1Sad#include <unistd.h>
371.1Sad#include <string.h>
381.1Sad#include <time.h>
391.1Sad#include <pthread.h>
401.1Sad#include <inttypes.h>
411.1Sad#include <signal.h>
421.1Sad
431.1Sad#define	MAXFILES	4096
441.1Sad
451.1Sadconst int primes[] = {
461.1Sad	233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
471.1Sad	293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359,
481.1Sad	367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
491.1Sad	433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491,
501.1Sad	499, 503, 509, 521, 523, 541,
511.1Sad};
521.1Sad
531.1Sadchar	**sa;
541.3Sadu_int	sasize;
551.3Sadu_int	sacnt;
561.1Sadstruct	timespec sts;
571.1Sadstruct	timespec ets;
581.1Sadpthread_barrier_t	barrier;
591.1Sadpthread_mutex_t	lock;
601.1Sadvolatile sig_atomic_t	stop;
611.1Saddouble	nlookups;
621.1Saddouble	ideal;
631.1Sad
641.1Sadstatic void
651.1Sadmakelist(void)
661.1Sad{
671.1Sad	char buf[MAXPATHLEN], *p;
681.1Sad	size_t l;
691.1Sad	FILE *fp;
701.1Sad
711.1Sad	fp = popen("/usr/bin/locate x", "r");
721.1Sad	if (fp == NULL) {
731.1Sad		perror("popen");
741.1Sad		exit(EXIT_FAILURE);
751.1Sad	}
761.1Sad
771.1Sad	while (fgets(buf, sizeof(buf), fp) != NULL) {
781.1Sad		l = strlen(buf) + 1;
791.1Sad		p = malloc(l);
801.1Sad		if (p == NULL) {
811.1Sad			perror("malloc");
821.1Sad			exit(EXIT_FAILURE);
831.1Sad		}
841.1Sad		strcpy(p, buf);
851.1Sad		p[l - 2] = '\0';
861.1Sad		if (sacnt == sasize) {
871.1Sad			sasize += 256;
881.1Sad			sa = realloc(sa, sizeof(*sa) * sasize);
891.1Sad			if (sa == NULL) {
901.1Sad				perror("realloc");
911.1Sad				exit(EXIT_FAILURE);
921.1Sad			}
931.1Sad		}
941.1Sad		sa[sacnt++] = p;
951.1Sad		if (sacnt == MAXFILES) {
961.1Sad			break;
971.1Sad		}
981.1Sad	}
991.1Sad
1001.1Sad	fclose(fp);
1011.1Sad}
1021.1Sad
1031.1Sadstatic void
1041.1Sadlookups(int idx)
1051.1Sad{
1061.3Sad	u_int p, c;
1071.1Sad
1081.1Sad	for (c = 0, p = 0; !stop; c++) {
1091.1Sad		p += primes[idx];
1101.1Sad		if (p >= sacnt) {
1111.1Sad			p %= sacnt;
1121.1Sad		}
1131.1Sad		(void)access(sa[p], F_OK);
1141.1Sad
1151.1Sad	}
1161.1Sad
1171.1Sad	pthread_mutex_lock(&lock);
1181.1Sad	nlookups += c;
1191.1Sad	pthread_mutex_unlock(&lock);
1201.1Sad}
1211.1Sad
1221.1Sadstatic void
1231.1Sadstart(void)
1241.1Sad{
1251.1Sad
1261.1Sad	(void)pthread_barrier_wait(&barrier);
1271.1Sad	if (clock_gettime(CLOCK_MONOTONIC, &sts)) {
1281.1Sad		perror("clock_gettime");
1291.1Sad		exit(EXIT_FAILURE);
1301.1Sad	}
1311.1Sad}
1321.1Sad
1331.1Sadstatic void
1341.1Sadend(void)
1351.1Sad{
1361.1Sad
1371.1Sad	if (clock_gettime(CLOCK_MONOTONIC, &ets)) {
1381.1Sad		perror("clock_gettime");
1391.1Sad		exit(EXIT_FAILURE);
1401.1Sad	}
1411.1Sad	(void)pthread_barrier_wait(&barrier);
1421.1Sad}
1431.1Sad
1441.1Sadstatic void *
1451.1Sadthread(void *cookie)
1461.1Sad{
1471.1Sad
1481.1Sad	start();
1491.1Sad	lookups((int)(uintptr_t)cookie);
1501.1Sad	end();
1511.1Sad
1521.1Sad	return NULL;
1531.1Sad}
1541.1Sad
1551.1Sadstatic void
1561.1Sadsigalrm(int junk)
1571.1Sad{
1581.1Sad
1591.1Sad	stop = (sig_atomic_t)1;
1601.1Sad}
1611.1Sad
1621.1Sadstatic void
1631.1Sadrun(int nt)
1641.1Sad{
1651.1Sad	pthread_t pt;
1661.1Sad	double c;
1671.1Sad	int i;
1681.1Sad	long us;
1691.1Sad
1701.1Sad	if (pthread_barrier_init(&barrier, NULL, nt + 1)) {
1711.1Sad		fprintf(stderr, "pthread_barrier_init\n");
1721.1Sad		exit(EXIT_FAILURE);
1731.1Sad	}
1741.1Sad
1751.1Sad	nlookups = 0;
1761.1Sad	stop = 0;
1771.1Sad	for (i = 0; i < nt; i++) {
1781.1Sad		if (pthread_create(&pt, NULL, thread, (void *)(uintptr_t)i)) {
1791.1Sad			fprintf(stderr, "pthread_create\n");
1801.1Sad			exit(EXIT_FAILURE);
1811.1Sad		}
1821.1Sad	}
1831.1Sad	start();
1841.1Sad	alarm(10);
1851.1Sad	end();
1861.1Sad	us = (long)(ets.tv_sec * (uint64_t)1000000 + ets.tv_nsec / 1000);
1871.1Sad	us -= (long)(sts.tv_sec * (uint64_t)1000000 + sts.tv_nsec / 1000);
1881.1Sad	c = nlookups * 1000000.0 / us;
1891.1Sad	if (ideal == 0) {
1901.1Sad		ideal = c;
1911.1Sad	}
1921.1Sad	printf("%d\t%d\t%.0f\t%.0f\n", sacnt, nt, c, ideal * nt);
1931.1Sad
1941.1Sad	if (pthread_barrier_destroy(&barrier)) {
1951.1Sad		fprintf(stderr, "pthread_barrier_destroy\n");
1961.1Sad		exit(EXIT_FAILURE);
1971.1Sad	}
1981.1Sad}
1991.1Sad
2001.1Sadint
2011.1Sadmain(int argc, char **argv)
2021.1Sad{
2031.1Sad	int i, mt;
2041.1Sad
2051.1Sad	(void)setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
2061.1Sad	if (argc < 2) {
2071.1Sad		mt = sysconf(_SC_NPROCESSORS_ONLN);
2081.1Sad	} else {
2091.1Sad		mt = atoi(argv[1]);
2101.1Sad		if (mt < 1) {
2111.1Sad			mt = 1;
2121.1Sad		}
2131.1Sad	}
2141.1Sad	if (pthread_mutex_init(&lock, NULL)) {
2151.1Sad		fprintf(stderr, "pthread_mutex_init\n");
2161.1Sad		exit(EXIT_FAILURE);
2171.1Sad	}
2181.1Sad	makelist();
2191.1Sad	(void)signal(SIGALRM, sigalrm);
2201.1Sad	printf("# nname\tnthr\tpersec\tideal\n");
2211.1Sad	for (i = 1; i <= mt; i++) {
2221.1Sad		run(i);
2231.1Sad	}
2241.1Sad	exit(EXIT_SUCCESS);
2251.1Sad}
226