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