blob: 68e8cbc2bde020d0b26a0e86d9bf108e0daffc38 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include <vppinfra/bitmap.h>
16#include <vppinfra/os.h>
17#include <vppinfra/qhash.h>
18#include <vppinfra/random.h>
19#include <vppinfra/time.h>
20
Dave Barachc3799992016-08-15 11:12:27 -040021typedef struct
22{
Ed Warnickecb9cada2015-12-08 15:45:58 -070023 u32 n_iter, seed, n_keys, n_hash_keys, verbose;
24
25 u32 max_vector;
26
Dave Barachc3799992016-08-15 11:12:27 -040027 uword *hash;
Ed Warnickecb9cada2015-12-08 15:45:58 -070028
Dave Barachc3799992016-08-15 11:12:27 -040029 uword *keys_in_hash_bitmap;
Ed Warnickecb9cada2015-12-08 15:45:58 -070030
Dave Barachc3799992016-08-15 11:12:27 -040031 u32 *qhash;
Ed Warnickecb9cada2015-12-08 15:45:58 -070032
Dave Barachc3799992016-08-15 11:12:27 -040033 uword *keys;
Ed Warnickecb9cada2015-12-08 15:45:58 -070034
Dave Barachc3799992016-08-15 11:12:27 -040035 uword *lookup_keys;
36 uword *lookup_key_indices;
37 u32 *lookup_results;
Ed Warnickecb9cada2015-12-08 15:45:58 -070038
Dave Barachc3799992016-08-15 11:12:27 -040039 u32 *get_multiple_results;
Ed Warnickecb9cada2015-12-08 15:45:58 -070040
41 clib_time_t time;
42
43 f64 overflow_fraction, ave_elts;
44 f64 get_time, hash_get_time;
45 f64 set_time, set_count;
46 f64 unset_time, unset_count;
47 f64 hash_set_time, hash_unset_time;
48} test_qhash_main_t;
49
50clib_error_t *
51test_qhash_main (unformat_input_t * input)
52{
Dave Barachc3799992016-08-15 11:12:27 -040053 clib_error_t *error = 0;
54 test_qhash_main_t _tm, *tm = &_tm;
Ed Warnickecb9cada2015-12-08 15:45:58 -070055 uword i, iter;
56
57 memset (tm, 0, sizeof (tm[0]));
58 tm->n_iter = 10;
59 tm->seed = 1;
60 tm->n_keys = 10;
61 tm->max_vector = 1;
62
63 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
64 {
65 if (unformat (input, "iter %d", &tm->n_iter))
66 ;
67 else if (unformat (input, "seed %d", &tm->seed))
68 ;
69 else if (unformat (input, "keys %d", &tm->n_keys))
70 ;
71 else if (unformat (input, "size %d", &tm->n_hash_keys))
72 ;
73 else if (unformat (input, "vector %d", &tm->max_vector))
74 ;
75 else if (unformat (input, "verbose"))
76 tm->verbose = 1;
77 else
78 {
79 error = clib_error_create ("unknown input `%U'\n",
80 format_unformat_error, input);
81 goto done;
82 }
83 }
84
Dave Barachc3799992016-08-15 11:12:27 -040085 if (!tm->seed)
Ed Warnickecb9cada2015-12-08 15:45:58 -070086 tm->seed = random_default_seed ();
87
88 clib_time_init (&tm->time);
89
90 clib_warning ("iter %d, seed %u, keys %d, max vector %d, ",
91 tm->n_iter, tm->seed, tm->n_keys, tm->max_vector);
92
93 vec_resize (tm->keys, tm->n_keys);
94 vec_resize (tm->get_multiple_results, tm->n_keys);
95 for (i = 0; i < vec_len (tm->keys); i++)
96 tm->keys[i] = random_uword (&tm->seed);
97
Dave Barachc3799992016-08-15 11:12:27 -040098 if (!tm->n_hash_keys)
Ed Warnickecb9cada2015-12-08 15:45:58 -070099 tm->n_hash_keys = 2 * max_pow2 (tm->n_keys);
100 tm->n_hash_keys = clib_max (tm->n_keys, tm->n_hash_keys);
101 qhash_resize (tm->qhash, tm->n_hash_keys);
102
103 {
Dave Barachc3799992016-08-15 11:12:27 -0400104 qhash_t *h = qhash_header (tm->qhash);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105 int i;
106 for (i = 0; i < ARRAY_LEN (h->hash_seeds); i++)
107 h->hash_seeds[i] = random_uword (&tm->seed);
108 }
109
110 vec_resize (tm->lookup_keys, tm->max_vector);
111 vec_resize (tm->lookup_key_indices, tm->max_vector);
112 vec_resize (tm->lookup_results, tm->max_vector);
113
114 for (iter = 0; iter < tm->n_iter; iter++)
115 {
Dave Barachc3799992016-08-15 11:12:27 -0400116 uword *p, j, n, is_set;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700117
118 n = tm->max_vector;
119
120 is_set = random_u32 (&tm->seed) & 1;
121 is_set |= hash_elts (tm->hash) < (tm->n_keys / 4);
122 if (hash_elts (tm->hash) > (3 * tm->n_keys) / 4)
123 is_set = 0;
124
125 _vec_len (tm->lookup_keys) = n;
126 _vec_len (tm->lookup_key_indices) = n;
127 j = 0;
128 while (j < n)
129 {
130 i = random_u32 (&tm->seed) % vec_len (tm->keys);
131 if (clib_bitmap_get (tm->keys_in_hash_bitmap, i) != is_set)
132 {
133 f64 t[2];
134 tm->lookup_key_indices[j] = i;
135 tm->lookup_keys[j] = tm->keys[i];
136 t[0] = clib_time_now (&tm->time);
137 if (is_set)
138 hash_set (tm->hash, tm->keys[i], i);
139 else
140 hash_unset (tm->hash, tm->keys[i]);
141 t[1] = clib_time_now (&tm->time);
142 if (is_set)
143 tm->hash_set_time += t[1] - t[0];
144 else
145 tm->hash_unset_time += t[1] - t[0];
146 tm->keys_in_hash_bitmap
Dave Barachc3799992016-08-15 11:12:27 -0400147 = clib_bitmap_set (tm->keys_in_hash_bitmap, i, is_set);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148 j++;
149 }
150 }
151
152 {
153 f64 t[2];
154
155 if (is_set)
156 {
157 t[0] = clib_time_now (&tm->time);
158 qhash_set_multiple (tm->qhash,
159 tm->lookup_keys,
160 vec_len (tm->lookup_keys),
161 tm->lookup_results);
162 t[1] = clib_time_now (&tm->time);
163 tm->set_time += t[1] - t[0];
164 tm->set_count += vec_len (tm->lookup_keys);
165 for (i = 0; i < vec_len (tm->lookup_keys); i++)
166 {
167 uword r = tm->lookup_results[i];
168 *vec_elt_at_index (tm->qhash, r) = tm->lookup_key_indices[i];
169 }
170 }
171 else
172 {
173 t[0] = clib_time_now (&tm->time);
174 qhash_unset_multiple (tm->qhash,
175 tm->lookup_keys,
176 vec_len (tm->lookup_keys),
177 tm->lookup_results);
178 t[1] = clib_time_now (&tm->time);
179 tm->unset_time += t[1] - t[0];
180 tm->unset_count += vec_len (tm->lookup_keys);
181
182 for (i = 0; i < vec_len (tm->lookup_keys); i++)
183 {
184 uword r = tm->lookup_results[i];
185 *vec_elt_at_index (tm->qhash, r) = ~0;
186 }
187 }
188 }
189
190 if (qhash_elts (tm->qhash) != hash_elts (tm->hash))
191 os_panic ();
192
193 {
Dave Barachc3799992016-08-15 11:12:27 -0400194 qhash_t *h;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195 uword i, k, l, count;
196
197 h = qhash_header (tm->qhash);
198
199 for (i = k = 0; k < vec_len (h->hash_key_valid_bitmap); k++)
200 i += count_set_bits (h->hash_key_valid_bitmap[k]);
201 k = hash_elts (h->overflow_hash);
202 l = qhash_elts (tm->qhash);
203 if (i + k != l)
204 os_panic ();
205
206 count = hash_elts (h->overflow_hash);
207 for (i = 0; i < (1 << h->log2_hash_size); i++)
208 count += tm->qhash[i] != ~0;
209 if (count != qhash_elts (tm->qhash))
210 os_panic ();
211
212 {
Dave Barachc3799992016-08-15 11:12:27 -0400213 u32 *tmp = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214
Dave Barachc3799992016-08-15 11:12:27 -0400215 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216 hash_foreach (k, l, h->overflow_hash, ({
217 j = qhash_hash_mix (h, k) / QHASH_KEYS_PER_BUCKET;
218 vec_validate (tmp, j);
219 tmp[j] += 1;
220 }));
Dave Barachc3799992016-08-15 11:12:27 -0400221 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222
223 for (k = 0; k < vec_len (tmp); k++)
224 {
225 if (k >= vec_len (h->overflow_counts))
226 os_panic ();
227 if (h->overflow_counts[k] != tmp[k])
228 os_panic ();
229 }
230 for (; k < vec_len (h->overflow_counts); k++)
231 if (h->overflow_counts[k] != 0)
232 os_panic ();
233
234 vec_free (tmp);
235 }
236 }
237
238 {
239 f64 t[2];
240
241 t[0] = clib_time_now (&tm->time);
242 qhash_get_multiple (tm->qhash, tm->keys, vec_len (tm->keys),
243 tm->get_multiple_results);
244 t[1] = clib_time_now (&tm->time);
245 tm->get_time += t[1] - t[0];
246
247 for (i = 0; i < vec_len (tm->keys); i++)
248 {
249 u32 r;
250
251 t[0] = clib_time_now (&tm->time);
252 p = hash_get (tm->hash, tm->keys[i]);
253 t[1] = clib_time_now (&tm->time);
254 tm->hash_get_time += t[1] - t[0];
255
256 r = qhash_get (tm->qhash, tm->keys[i]);
257 if (p)
258 {
259 if (p[0] != i)
260 os_panic ();
Dave Barachc3799992016-08-15 11:12:27 -0400261 if (*vec_elt_at_index (tm->qhash, r) != i)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700262 os_panic ();
263 }
264 else
265 {
266 if (r != ~0)
267 os_panic ();
268 }
269 if (r != tm->get_multiple_results[i])
270 os_panic ();
271 }
272 }
273
274 tm->overflow_fraction +=
275 ((f64) qhash_n_overflow (tm->qhash) / qhash_elts (tm->qhash));
276 tm->ave_elts += qhash_elts (tm->qhash);
277 }
278
279 fformat (stderr, "%d iter %.6e overflow, %.4f ave. elts\n",
280 tm->n_iter,
Dave Barachc3799992016-08-15 11:12:27 -0400281 tm->overflow_fraction / tm->n_iter, tm->ave_elts / tm->n_iter);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282
283 tm->get_time /= tm->n_iter * vec_len (tm->keys);
284 tm->hash_get_time /= tm->n_iter * vec_len (tm->keys);
285
286 tm->set_time /= tm->set_count;
287 tm->unset_time /= tm->unset_count;
288 tm->hash_set_time /= tm->set_count;
289 tm->hash_unset_time /= tm->unset_count;
290
Dave Barachc3799992016-08-15 11:12:27 -0400291 fformat (stderr,
292 "get/set/unset clocks %.2e %.2e %.2e clib %.2e %.2e %.2e ratio %.2f %.2f %.2f\n",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700293 tm->get_time * tm->time.clocks_per_second,
294 tm->set_time * tm->time.clocks_per_second,
295 tm->unset_time * tm->time.clocks_per_second,
296 tm->hash_get_time * tm->time.clocks_per_second,
297 tm->hash_set_time * tm->time.clocks_per_second,
298 tm->hash_unset_time * tm->time.clocks_per_second,
Dave Barachc3799992016-08-15 11:12:27 -0400299 tm->hash_get_time / tm->get_time, tm->hash_set_time / tm->set_time,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700300 tm->hash_unset_time / tm->unset_time);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700301
Dave Barachc3799992016-08-15 11:12:27 -0400302
303done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700304 return error;
305}
306
307#ifdef CLIB_UNIX
Dave Barachc3799992016-08-15 11:12:27 -0400308int
309main (int argc, char *argv[])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700310{
311 unformat_input_t i;
Dave Barachc3799992016-08-15 11:12:27 -0400312 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700313
Damjan Marion4dffd1c2018-09-03 12:30:36 +0200314 clib_mem_init (0, 64ULL << 20);
315
Ed Warnickecb9cada2015-12-08 15:45:58 -0700316 unformat_init_command_line (&i, argv);
317 error = test_qhash_main (&i);
318 unformat_free (&i);
319 if (error)
320 {
321 clib_error_report (error);
322 return 1;
323 }
324 else
325 return 0;
326}
327#endif /* CLIB_UNIX */
Dave Barachc3799992016-08-15 11:12:27 -0400328
329/*
330 * fd.io coding-style-patch-verification: ON
331 *
332 * Local Variables:
333 * eval: (c-set-style "gnu")
334 * End:
335 */