xref: /minix3/usr.bin/nbperf/nbperf.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: nbperf.c,v 1.5 2013/01/31 16:32:02 joerg Exp $	*/
2c75851fcSLionel Sambuc /*-
3c75851fcSLionel Sambuc  * Copyright (c) 2009 The NetBSD Foundation, Inc.
4c75851fcSLionel Sambuc  * All rights reserved.
5c75851fcSLionel Sambuc  *
6c75851fcSLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
7c75851fcSLionel Sambuc  * by Joerg Sonnenberger.
8c75851fcSLionel Sambuc  *
9c75851fcSLionel Sambuc  * Redistribution and use in source and binary forms, with or without
10c75851fcSLionel Sambuc  * modification, are permitted provided that the following conditions
11c75851fcSLionel Sambuc  * are met:
12c75851fcSLionel Sambuc  *
13c75851fcSLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14c75851fcSLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15c75851fcSLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16c75851fcSLionel Sambuc  *    notice, this list of conditions and the following disclaimer in
17c75851fcSLionel Sambuc  *    the documentation and/or other materials provided with the
18c75851fcSLionel Sambuc  *    distribution.
19c75851fcSLionel Sambuc  *
20c75851fcSLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21c75851fcSLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22c75851fcSLionel Sambuc  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23c75851fcSLionel Sambuc  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
24c75851fcSLionel Sambuc  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25c75851fcSLionel Sambuc  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26c75851fcSLionel Sambuc  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27c75851fcSLionel Sambuc  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28c75851fcSLionel Sambuc  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29c75851fcSLionel Sambuc  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30c75851fcSLionel Sambuc  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c75851fcSLionel Sambuc  * SUCH DAMAGE.
32c75851fcSLionel Sambuc  */
33c75851fcSLionel Sambuc 
34c75851fcSLionel Sambuc #if HAVE_NBTOOL_CONFIG_H
35c75851fcSLionel Sambuc #include "nbtool_config.h"
36c75851fcSLionel Sambuc #endif
37c75851fcSLionel Sambuc 
38c75851fcSLionel Sambuc #include <sys/cdefs.h>
39*84d9c625SLionel Sambuc __RCSID("$NetBSD: nbperf.c,v 1.5 2013/01/31 16:32:02 joerg Exp $");
40c75851fcSLionel Sambuc 
41c75851fcSLionel Sambuc #include <sys/endian.h>
42c75851fcSLionel Sambuc #include <err.h>
43c75851fcSLionel Sambuc #include <errno.h>
44c75851fcSLionel Sambuc #include <inttypes.h>
45c75851fcSLionel Sambuc #include <stdlib.h>
46c75851fcSLionel Sambuc #include <stdio.h>
47c75851fcSLionel Sambuc #include <string.h>
48c75851fcSLionel Sambuc #include <unistd.h>
49c75851fcSLionel Sambuc 
50c75851fcSLionel Sambuc #include "nbperf.h"
51c75851fcSLionel Sambuc 
52c75851fcSLionel Sambuc static int predictable;
53c75851fcSLionel Sambuc 
54c75851fcSLionel Sambuc static __dead
usage(void)55c75851fcSLionel Sambuc void usage(void)
56c75851fcSLionel Sambuc {
57c75851fcSLionel Sambuc 	fprintf(stderr,
58c75851fcSLionel Sambuc 	    "%s [-ps] [-c utilisation] [-i iterations] [-n name] "
59c75851fcSLionel Sambuc 	    "[-o output] input\n",
60c75851fcSLionel Sambuc 	    getprogname());
61c75851fcSLionel Sambuc 	exit(1);
62c75851fcSLionel Sambuc }
63c75851fcSLionel Sambuc 
64c75851fcSLionel Sambuc #if HAVE_NBTOOL_CONFIG_H && !defined(__NetBSD__)
65c75851fcSLionel Sambuc #define	arc4random() rand()
66c75851fcSLionel Sambuc #endif
67c75851fcSLionel Sambuc 
68c75851fcSLionel Sambuc static void
mi_vector_hash_seed_hash(struct nbperf * nbperf)69c75851fcSLionel Sambuc mi_vector_hash_seed_hash(struct nbperf *nbperf)
70c75851fcSLionel Sambuc {
71c75851fcSLionel Sambuc 	static uint32_t predictable_counter;
72c75851fcSLionel Sambuc 	if (predictable)
73c75851fcSLionel Sambuc 		nbperf->seed[0] = predictable_counter++;
74c75851fcSLionel Sambuc 	else
75c75851fcSLionel Sambuc 		nbperf->seed[0] = arc4random();
76c75851fcSLionel Sambuc }
77c75851fcSLionel Sambuc 
78c75851fcSLionel Sambuc static void
mi_vector_hash_compute(struct nbperf * nbperf,const void * key,size_t keylen,uint32_t * hashes)79c75851fcSLionel Sambuc mi_vector_hash_compute(struct nbperf *nbperf, const void *key, size_t keylen,
80c75851fcSLionel Sambuc     uint32_t *hashes)
81c75851fcSLionel Sambuc {
82c75851fcSLionel Sambuc 	mi_vector_hash(key, keylen, nbperf->seed[0], hashes);
83c75851fcSLionel Sambuc }
84c75851fcSLionel Sambuc 
85c75851fcSLionel Sambuc static void
mi_vector_hash_print_hash(struct nbperf * nbperf,const char * indent,const char * key,const char * keylen,const char * hash)86c75851fcSLionel Sambuc mi_vector_hash_print_hash(struct nbperf *nbperf, const char *indent,
87c75851fcSLionel Sambuc     const char *key, const char *keylen, const char *hash)
88c75851fcSLionel Sambuc {
89c75851fcSLionel Sambuc 	fprintf(nbperf->output,
90c75851fcSLionel Sambuc 	    "%smi_vector_hash(%s, %s, 0x%08" PRIx32 "U, %s);\n",
91c75851fcSLionel Sambuc 	    indent, key, keylen, nbperf->seed[0], hash);
92c75851fcSLionel Sambuc }
93c75851fcSLionel Sambuc 
94c75851fcSLionel Sambuc static void
set_hash(struct nbperf * nbperf,const char * arg)95c75851fcSLionel Sambuc set_hash(struct nbperf *nbperf, const char *arg)
96c75851fcSLionel Sambuc {
97c75851fcSLionel Sambuc 	if (strcmp(arg, "mi_vector_hash") == 0) {
98c75851fcSLionel Sambuc 		nbperf->hash_size = 3;
99c75851fcSLionel Sambuc 		nbperf->seed_hash = mi_vector_hash_seed_hash;
100c75851fcSLionel Sambuc 		nbperf->compute_hash = mi_vector_hash_compute;
101c75851fcSLionel Sambuc 		nbperf->print_hash = mi_vector_hash_print_hash;
102c75851fcSLionel Sambuc 		return;
103c75851fcSLionel Sambuc 	}
104c75851fcSLionel Sambuc 	if (nbperf->hash_size > NBPERF_MAX_HASH_SIZE)
105c75851fcSLionel Sambuc 		errx(1, "Hash function creates too many output values");
106c75851fcSLionel Sambuc 	errx(1, "Unknown hash function: %s", arg);
107c75851fcSLionel Sambuc }
108c75851fcSLionel Sambuc 
109c75851fcSLionel Sambuc int
main(int argc,char ** argv)110c75851fcSLionel Sambuc main(int argc, char **argv)
111c75851fcSLionel Sambuc {
112c75851fcSLionel Sambuc 	struct nbperf nbperf = {
113c75851fcSLionel Sambuc 	    .c = 0,
114c75851fcSLionel Sambuc 	    .hash_name = "hash",
115c75851fcSLionel Sambuc 	    .map_output = NULL,
116c75851fcSLionel Sambuc 	    .output = NULL,
117c75851fcSLionel Sambuc 	    .static_hash = 0,
118c75851fcSLionel Sambuc 	    .first_round = 1,
119c75851fcSLionel Sambuc 	    .has_duplicates = 0,
120c75851fcSLionel Sambuc 	};
121c75851fcSLionel Sambuc 	FILE *input;
122c75851fcSLionel Sambuc 	size_t curlen = 0, curalloc = 0;
123c75851fcSLionel Sambuc 	char *line, *eos;
124c75851fcSLionel Sambuc 	ssize_t line_len;
125c75851fcSLionel Sambuc 	size_t line_allocated;
126c75851fcSLionel Sambuc 	const void **keys = NULL;
127c75851fcSLionel Sambuc 	size_t *keylens = NULL;
128c75851fcSLionel Sambuc 	uint32_t max_iterations = 0xffffffU;
129c75851fcSLionel Sambuc 	long long tmp;
130c75851fcSLionel Sambuc 	int looped, ch;
131c75851fcSLionel Sambuc 	int (*build_hash)(struct nbperf *) = chm_compute;
132c75851fcSLionel Sambuc 
133c75851fcSLionel Sambuc 	set_hash(&nbperf, "mi_vector_hash");
134c75851fcSLionel Sambuc 
135c75851fcSLionel Sambuc 	while ((ch = getopt(argc, argv, "a:c:h:i:m:n:o:ps")) != -1) {
136c75851fcSLionel Sambuc 		switch (ch) {
137c75851fcSLionel Sambuc 		case 'a':
138*84d9c625SLionel Sambuc 			/* Accept bdz as alias for netbsd-6 compat. */
139c75851fcSLionel Sambuc 			if (strcmp(optarg, "chm") == 0)
140c75851fcSLionel Sambuc 				build_hash = chm_compute;
141c75851fcSLionel Sambuc 			else if (strcmp(optarg, "chm3") == 0)
142c75851fcSLionel Sambuc 				build_hash = chm3_compute;
143*84d9c625SLionel Sambuc 			else if (strcmp(optarg, "bpz") == 0 ||
144*84d9c625SLionel Sambuc 			         strcmp(optarg, "bdz") == 0)
145*84d9c625SLionel Sambuc 				build_hash = bpz_compute;
146c75851fcSLionel Sambuc 			else
147c75851fcSLionel Sambuc 				errx(1, "Unsupport algorithm: %s", optarg);
148c75851fcSLionel Sambuc 			break;
149c75851fcSLionel Sambuc 		case 'c':
150c75851fcSLionel Sambuc 			errno = 0;
151c75851fcSLionel Sambuc 			nbperf.c = strtod(optarg, &eos);
152c75851fcSLionel Sambuc 			if (errno || eos[0] || !nbperf.c)
153c75851fcSLionel Sambuc 				errx(2, "Invalid argument for -c");
154c75851fcSLionel Sambuc 			break;
155c75851fcSLionel Sambuc 		case 'h':
156c75851fcSLionel Sambuc 			set_hash(&nbperf, optarg);
157c75851fcSLionel Sambuc 			break;
158c75851fcSLionel Sambuc 		case 'i':
159c75851fcSLionel Sambuc 			errno = 0;
160c75851fcSLionel Sambuc 			tmp = strtoll(optarg, &eos, 0);
161c75851fcSLionel Sambuc 			if (errno || eos == optarg || eos[0] ||
162c75851fcSLionel Sambuc 			    tmp < 0 || tmp > 0xffffffffU)
163c75851fcSLionel Sambuc 				errx(2, "Iteration count must be "
164c75851fcSLionel Sambuc 				    "a 32bit integer");
165c75851fcSLionel Sambuc 			max_iterations = (uint32_t)tmp;
166c75851fcSLionel Sambuc 			break;
167c75851fcSLionel Sambuc 		case 'm':
168c75851fcSLionel Sambuc 			if (nbperf.map_output)
169c75851fcSLionel Sambuc 				fclose(nbperf.map_output);
170c75851fcSLionel Sambuc 			nbperf.map_output = fopen(optarg, "w");
171c75851fcSLionel Sambuc 			if (nbperf.map_output == NULL)
172c75851fcSLionel Sambuc 				err(2, "cannot open map file");
173c75851fcSLionel Sambuc 			break;
174c75851fcSLionel Sambuc 		case 'n':
175c75851fcSLionel Sambuc 			nbperf.hash_name = optarg;
176c75851fcSLionel Sambuc 			break;
177c75851fcSLionel Sambuc 		case 'o':
178c75851fcSLionel Sambuc 			if (nbperf.output)
179c75851fcSLionel Sambuc 				fclose(nbperf.output);
180c75851fcSLionel Sambuc 			nbperf.output = fopen(optarg, "w");
181c75851fcSLionel Sambuc 			if (nbperf.output == NULL)
182c75851fcSLionel Sambuc 				err(2, "cannot open output file");
183c75851fcSLionel Sambuc 			break;
184c75851fcSLionel Sambuc 		case 'p':
185c75851fcSLionel Sambuc 			predictable = 1;
186c75851fcSLionel Sambuc 			break;
187c75851fcSLionel Sambuc 		case 's':
188c75851fcSLionel Sambuc 			nbperf.static_hash = 1;
189c75851fcSLionel Sambuc 			break;
190c75851fcSLionel Sambuc 		default:
191c75851fcSLionel Sambuc 			usage();
192c75851fcSLionel Sambuc 		}
193c75851fcSLionel Sambuc 	}
194c75851fcSLionel Sambuc 
195c75851fcSLionel Sambuc 	argc -= optind;
196c75851fcSLionel Sambuc 	argv += optind;
197c75851fcSLionel Sambuc 
198c75851fcSLionel Sambuc 	if (argc > 1)
199c75851fcSLionel Sambuc 		usage();
200c75851fcSLionel Sambuc 
201c75851fcSLionel Sambuc 	if (argc == 1) {
202c75851fcSLionel Sambuc 		input = fopen(argv[0], "r");
203c75851fcSLionel Sambuc 		if (input == NULL)
204c75851fcSLionel Sambuc 			err(1, "can't open input file");
205c75851fcSLionel Sambuc 	} else
206c75851fcSLionel Sambuc 		input = stdin;
207c75851fcSLionel Sambuc 
208c75851fcSLionel Sambuc 	if (nbperf.output == NULL)
209c75851fcSLionel Sambuc 		nbperf.output = stdout;
210c75851fcSLionel Sambuc 
211c75851fcSLionel Sambuc 	line = NULL;
212c75851fcSLionel Sambuc 	line_allocated = 0;
213c75851fcSLionel Sambuc 	while ((line_len = getline(&line, &line_allocated, input)) != -1) {
214c75851fcSLionel Sambuc 		if (line_len && line[line_len - 1] == '\n')
215c75851fcSLionel Sambuc 			--line_len;
216c75851fcSLionel Sambuc 		if (curlen == curalloc) {
217c75851fcSLionel Sambuc 			if (curalloc < 256)
218c75851fcSLionel Sambuc 				curalloc = 256;
219c75851fcSLionel Sambuc 			else
220c75851fcSLionel Sambuc 				curalloc += curalloc;
221c75851fcSLionel Sambuc 			keys = realloc(keys, curalloc * sizeof(*keys));
222c75851fcSLionel Sambuc 			if (keys == NULL)
223c75851fcSLionel Sambuc 				err(1, "realloc failed");
224c75851fcSLionel Sambuc 			keylens = realloc(keylens,
225c75851fcSLionel Sambuc 			    curalloc * sizeof(*keylens));
226c75851fcSLionel Sambuc 			if (keylens == NULL)
227c75851fcSLionel Sambuc 				err(1, "realloc failed");
228c75851fcSLionel Sambuc 		}
229c75851fcSLionel Sambuc 		if ((keys[curlen] = strndup(line, line_len)) == NULL)
230c75851fcSLionel Sambuc 			err(1, "malloc failed");
231c75851fcSLionel Sambuc 		keylens[curlen] = line_len;
232c75851fcSLionel Sambuc 		++curlen;
233c75851fcSLionel Sambuc 	}
234c75851fcSLionel Sambuc 	free(line);
235c75851fcSLionel Sambuc 
236c75851fcSLionel Sambuc 	if (input != stdin)
237c75851fcSLionel Sambuc 		fclose(input);
238c75851fcSLionel Sambuc 
239c75851fcSLionel Sambuc 	nbperf.n = curlen;
240c75851fcSLionel Sambuc 	nbperf.keys = keys;
241c75851fcSLionel Sambuc 	nbperf.keylens = keylens;
242c75851fcSLionel Sambuc 
243c75851fcSLionel Sambuc 	looped = 0;
244c75851fcSLionel Sambuc 	while ((*build_hash)(&nbperf)) {
245c75851fcSLionel Sambuc 		if (nbperf.has_duplicates)
246c75851fcSLionel Sambuc 			errx(1, "Duplicate keys detected");
247c75851fcSLionel Sambuc 		fputc('.', stderr);
248c75851fcSLionel Sambuc 		looped = 1;
249c75851fcSLionel Sambuc 		if (max_iterations == 0xffffffffU)
250c75851fcSLionel Sambuc 			continue;
251c75851fcSLionel Sambuc 		if (--max_iterations == 0) {
252c75851fcSLionel Sambuc 			fputc('\n', stderr);
253c75851fcSLionel Sambuc 			errx(1, "Iteration count reached");
254c75851fcSLionel Sambuc 		}
255c75851fcSLionel Sambuc 	}
256c75851fcSLionel Sambuc 	if (looped)
257c75851fcSLionel Sambuc 		fputc('\n', stderr);
258c75851fcSLionel Sambuc 
259c75851fcSLionel Sambuc 	return 0;
260c75851fcSLionel Sambuc }
261