Initial commit of vpp code.
[vpp.git] / vppinfra / vppinfra / test_vhash.c
1 /*
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 /*
16   Copyright (c) 2010 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #if 0
39 #ifdef __OPTIMIZE__
40 #undef CLIB_DEBUG
41 #endif
42 #endif
43
44 #include <vppinfra/bitmap.h>
45 #include <vppinfra/error.h>
46 #include <vppinfra/os.h>
47 #include <vppinfra/random.h>
48 #include <vppinfra/time.h>
49 #include <vppinfra/vhash.h>
50
51 #ifdef CLIB_HAVE_VEC128
52
53 typedef struct {
54   u32 n_iter;
55   u32 seed;
56   u32 verbose;
57   u32 n_keys;
58   u32 log2_size;
59   u32 n_key_u32;
60
61   u32 n_vectors_div_4;
62   u32 n_vectors_mod_4;
63
64   u32 * keys;
65   u32 * results;
66
67   u32 * vhash_get_key_indices;
68   u32 * vhash_get_results;
69
70   u32 * vhash_key_indices;
71   u32 * vhash_results;
72
73   vhash_t vhash;
74
75   uword ** key_hash;
76
77   struct {
78     u64 n_clocks;
79     u64 n_vectors;
80     u64 n_calls;
81   } get_stats, set_stats, unset_stats;
82 } test_vhash_main_t;
83
84 always_inline u32
85 test_vhash_key_gather (void * _tm, u32 vi, u32 wi, u32 n_key_u32s)
86 {
87   test_vhash_main_t * tm = _tm;
88   ASSERT (n_key_u32s == tm->n_key_u32);
89   ASSERT (wi < n_key_u32s);
90   vi = vec_elt (tm->vhash_key_indices, vi);
91   return vec_elt (tm->keys, vi * n_key_u32s + wi);
92 }
93
94 always_inline u32x4
95 test_vhash_4key_gather (void * _tm, u32 vi, u32 wi, u32 n_key_u32s)
96 {
97   test_vhash_main_t * tm = _tm;
98   u32 * p;
99   u32x4_union_t x;
100
101   ASSERT (n_key_u32s == tm->n_key_u32);
102   ASSERT (wi < n_key_u32s);
103
104   p = vec_elt_at_index (tm->vhash_key_indices, vi + 0);
105   x.as_u32[0] = tm->keys[p[0] * n_key_u32s + wi];
106   x.as_u32[1] = tm->keys[p[1] * n_key_u32s + wi];
107   x.as_u32[2] = tm->keys[p[2] * n_key_u32s + wi];
108   x.as_u32[3] = tm->keys[p[3] * n_key_u32s + wi];
109   return x.as_u32x4;
110 }
111
112 always_inline u32
113 test_vhash_get_result (void * _tm,
114                        u32 vector_index,
115                        u32 result_index,
116                        u32 n_key_u32s)
117 {
118   test_vhash_main_t * tm = _tm;
119   u32 * p = vec_elt_at_index (tm->vhash_results, vector_index);
120   p[0] = result_index;
121   return result_index;
122 }
123
124 always_inline u32x4
125 test_vhash_get_4result (void * _tm,
126                         u32 vector_index,
127                         u32x4 results,
128                         u32 n_key_u32s)
129 {
130   test_vhash_main_t * tm = _tm;
131   u32 * p = vec_elt_at_index (tm->vhash_results, vector_index);
132   *(u32x4 *)p = results;
133   return results;
134 }
135
136 always_inline u32
137 test_vhash_set_result (void * _tm,
138                        u32 vector_index,
139                        u32 old_result,
140                        u32 n_key_u32s)
141 {
142   test_vhash_main_t * tm = _tm;
143   u32 * p = vec_elt_at_index (tm->vhash_results, vector_index);
144   u32 new_result = p[0];
145   p[0] = old_result;
146   return new_result;
147 }
148
149 always_inline u32
150 test_vhash_unset_result (void * _tm, u32 i, u32 old_result, u32 n_key_u32s)
151 {
152   test_vhash_main_t * tm = _tm;
153   u32 * p = vec_elt_at_index (tm->vhash_results, i);
154   p[0] = old_result;
155   return 0;
156 }
157
158 #define _(N_KEY_U32)                                                    \
159   always_inline u32                                                     \
160   test_vhash_key_gather_##N_KEY_U32 (void * _tm, u32 vi, u32 i)         \
161   { return test_vhash_key_gather (_tm, vi, i, N_KEY_U32); }             \
162                                                                         \
163   always_inline u32x4                                                   \
164   test_vhash_key_gather_4_##N_KEY_U32 (void * _tm, u32 vi, u32 i)       \
165   {  return test_vhash_4key_gather (_tm, vi, i, N_KEY_U32); }           \
166                                                                         \
167   clib_pipeline_stage                                                   \
168   (test_vhash_gather_keys_stage_##N_KEY_U32,                            \
169    test_vhash_main_t *, tm, i,                                          \
170    {                                                                    \
171      vhash_gather_4key_stage                                            \
172        (&tm->vhash,                                                     \
173         /* vector_index */ i,                                           \
174         test_vhash_key_gather_4_##N_KEY_U32,                            \
175         tm,                                                             \
176         N_KEY_U32);                                                     \
177    })                                                                   \
178                                                                         \
179   clib_pipeline_stage_no_inline                                         \
180   (test_vhash_gather_keys_mod_stage_##N_KEY_U32,                        \
181    test_vhash_main_t *, tm, i,                                          \
182    {                                                                    \
183      vhash_gather_key_stage                                             \
184        (&tm->vhash,                                                     \
185         /* vector_index */ tm->n_vectors_div_4,                         \
186         /* n_vectors */ tm->n_vectors_mod_4,                            \
187         test_vhash_key_gather_##N_KEY_U32,                              \
188         tm,                                                             \
189         N_KEY_U32);                                                     \
190    })                                                                   \
191                                                                         \
192   clib_pipeline_stage                                                   \
193   (test_vhash_hash_finalize_stage_##N_KEY_U32,                          \
194    test_vhash_main_t *, tm, i,                                          \
195    {                                                                    \
196      vhash_finalize_stage (&tm->vhash, i, N_KEY_U32);                   \
197    })                                                                   \
198                                                                         \
199   clib_pipeline_stage_no_inline                                         \
200   (test_vhash_hash_finalize_mod_stage_##N_KEY_U32,                      \
201    test_vhash_main_t *, tm, i,                                          \
202    {                                                                    \
203      vhash_finalize_stage (&tm->vhash, tm->n_vectors_div_4, N_KEY_U32); \
204    })                                                                   \
205                                                                         \
206   clib_pipeline_stage                                                   \
207   (test_vhash_get_stage_##N_KEY_U32,                                    \
208    test_vhash_main_t *, tm, i,                                          \
209    {                                                                    \
210      vhash_get_4_stage (&tm->vhash,                                     \
211                         /* vector_index */ i,                           \
212                         test_vhash_get_4result,                         \
213                         tm, N_KEY_U32);                                 \
214    })                                                                   \
215                                                                         \
216   clib_pipeline_stage_no_inline                                         \
217   (test_vhash_get_mod_stage_##N_KEY_U32,                                \
218    test_vhash_main_t *, tm, i,                                          \
219    {                                                                    \
220      vhash_get_stage (&tm->vhash,                                       \
221                       /* vector_index */ tm->n_vectors_div_4,           \
222                       /* n_vectors */ tm->n_vectors_mod_4,              \
223                       test_vhash_get_result,                            \
224                       tm, N_KEY_U32);                                   \
225    })                                                                   \
226                                                                         \
227   clib_pipeline_stage                                                   \
228   (test_vhash_set_stage_##N_KEY_U32,                                    \
229    test_vhash_main_t *, tm, i,                                          \
230    {                                                                    \
231      vhash_set_stage (&tm->vhash,                                       \
232                       /* vector_index */ i,                             \
233                       /* n_vectors */ VECTOR_WORD_TYPE_LEN (u32),       \
234                       test_vhash_set_result,                            \
235                       tm, N_KEY_U32);                                   \
236    })                                                                   \
237                                                                         \
238   clib_pipeline_stage_no_inline                                         \
239   (test_vhash_set_mod_stage_##N_KEY_U32,                                \
240    test_vhash_main_t *, tm, i,                                          \
241    {                                                                    \
242      vhash_set_stage (&tm->vhash,                                       \
243                       /* vector_index */ tm->n_vectors_div_4,           \
244                       /* n_vectors */ tm->n_vectors_mod_4,              \
245                       test_vhash_set_result,                            \
246                       tm, N_KEY_U32);                                   \
247    })                                                                   \
248                                                                         \
249   clib_pipeline_stage                                                   \
250   (test_vhash_unset_stage_##N_KEY_U32,                                  \
251    test_vhash_main_t *, tm, i,                                          \
252    {                                                                    \
253      vhash_unset_stage (&tm->vhash,                                     \
254                         /* vector_index */ i,                           \
255                         /* n_vectors */ VECTOR_WORD_TYPE_LEN (u32),     \
256                         test_vhash_unset_result,                        \
257                         tm, N_KEY_U32);                                 \
258    })                                                                   \
259                                                                         \
260   clib_pipeline_stage_no_inline                                         \
261   (test_vhash_unset_mod_stage_##N_KEY_U32,                              \
262    test_vhash_main_t *, tm, i,                                          \
263    {                                                                    \
264      vhash_unset_stage (&tm->vhash,                                     \
265                         /* vector_index */ tm->n_vectors_div_4,         \
266                         /* n_vectors */ tm->n_vectors_mod_4,            \
267                         test_vhash_unset_result,                        \
268                         tm, N_KEY_U32);                                 \
269    })
270
271 _ (1);
272 _ (2);
273 _ (3);
274 _ (4);
275 _ (5);
276 _ (6);
277
278 #undef _
279
280 #define _(N_KEY_U32)                                                    \
281   clib_pipeline_stage                                                   \
282   (test_vhash_hash_mix_stage_##N_KEY_U32,                               \
283    test_vhash_main_t *, tm, i,                                          \
284    {                                                                    \
285      vhash_mix_stage (&tm->vhash, i, N_KEY_U32);                        \
286    })                                                                   \
287                                                                         \
288   clib_pipeline_stage_no_inline                                         \
289   (test_vhash_hash_mix_mod_stage_##N_KEY_U32,                           \
290    test_vhash_main_t *, tm, i,                                          \
291    {                                                                    \
292      vhash_mix_stage (&tm->vhash, tm->n_vectors_div_4, N_KEY_U32);      \
293    })
294
295 _ (4);
296 _ (5);
297 _ (6);
298
299 #undef _
300
301 typedef enum {
302   GET, SET, UNSET,
303 } test_vhash_op_t;
304
305 static void
306 test_vhash_op (test_vhash_main_t * tm,
307                u32 * key_indices,
308                u32 * results,
309                uword n_keys,
310                test_vhash_op_t op)
311 {
312   vhash_validate_sizes (&tm->vhash, tm->n_key_u32, n_keys);
313
314   tm->vhash_results = results;
315   tm->vhash_key_indices = key_indices;
316   tm->n_vectors_div_4 = n_keys / 4;
317   tm->n_vectors_mod_4 = n_keys % 4;
318
319   if (tm->n_vectors_div_4 > 0)
320     {
321       switch (tm->n_key_u32)
322         {
323         default:
324           ASSERT (0);
325           break;
326
327 #define _(N_KEY_U32)                                            \
328         case N_KEY_U32:                                         \
329           if (op == GET)                                        \
330             clib_pipeline_run_3_stage                           \
331               (tm->n_vectors_div_4,                             \
332                tm,                                              \
333                test_vhash_gather_keys_stage_##N_KEY_U32,        \
334                test_vhash_hash_finalize_stage_##N_KEY_U32,      \
335                test_vhash_get_stage_##N_KEY_U32);               \
336           else if (op == SET)                                   \
337             clib_pipeline_run_3_stage                           \
338               (tm->n_vectors_div_4,                             \
339                tm,                                              \
340                test_vhash_gather_keys_stage_##N_KEY_U32,        \
341                test_vhash_hash_finalize_stage_##N_KEY_U32,      \
342                test_vhash_set_stage_##N_KEY_U32);               \
343           else                                                  \
344             clib_pipeline_run_3_stage                           \
345               (tm->n_vectors_div_4,                             \
346                tm,                                              \
347                test_vhash_gather_keys_stage_##N_KEY_U32,        \
348                test_vhash_hash_finalize_stage_##N_KEY_U32,      \
349                test_vhash_unset_stage_##N_KEY_U32);             \
350           break;
351
352               _ (1);
353               _ (2);
354               _ (3);
355
356 #undef _
357
358 #define _(N_KEY_U32)                                            \
359         case N_KEY_U32:                                         \
360           if (op == GET)                                        \
361             clib_pipeline_run_4_stage                           \
362               (tm->n_vectors_div_4,                             \
363                tm,                                              \
364                test_vhash_gather_keys_stage_##N_KEY_U32,        \
365                test_vhash_hash_mix_stage_##N_KEY_U32,           \
366                test_vhash_hash_finalize_stage_##N_KEY_U32,      \
367                test_vhash_get_stage_##N_KEY_U32);               \
368           else if (op == SET)                                   \
369             clib_pipeline_run_4_stage                           \
370               (tm->n_vectors_div_4,                             \
371                tm,                                              \
372                test_vhash_gather_keys_stage_##N_KEY_U32,        \
373                test_vhash_hash_mix_stage_##N_KEY_U32,           \
374                test_vhash_hash_finalize_stage_##N_KEY_U32,      \
375                test_vhash_set_stage_##N_KEY_U32);               \
376           else                                                  \
377             clib_pipeline_run_4_stage                           \
378               (tm->n_vectors_div_4,                             \
379                tm,                                              \
380                test_vhash_gather_keys_stage_##N_KEY_U32,        \
381                test_vhash_hash_mix_stage_##N_KEY_U32,           \
382                test_vhash_hash_finalize_stage_##N_KEY_U32,      \
383                test_vhash_unset_stage_##N_KEY_U32);             \
384           break;
385
386               _ (4);
387               _ (5);
388               _ (6);
389
390 #undef _
391         }
392     }
393
394
395   if (tm->n_vectors_mod_4 > 0)
396     {
397       switch (tm->n_key_u32)
398         {
399         default:
400           ASSERT (0);
401           break;
402
403 #define _(N_KEY_U32)                                            \
404         case N_KEY_U32:                                         \
405           if (op == GET)                                        \
406             clib_pipeline_run_3_stage                           \
407               (1,                                               \
408                tm,                                              \
409                test_vhash_gather_keys_mod_stage_##N_KEY_U32,    \
410                test_vhash_hash_finalize_mod_stage_##N_KEY_U32,  \
411                test_vhash_get_mod_stage_##N_KEY_U32);           \
412           else if (op == SET)                                   \
413             clib_pipeline_run_3_stage                           \
414               (1,                                               \
415                tm,                                              \
416                test_vhash_gather_keys_mod_stage_##N_KEY_U32,    \
417                test_vhash_hash_finalize_mod_stage_##N_KEY_U32,  \
418                test_vhash_set_mod_stage_##N_KEY_U32);           \
419           else                                                  \
420             clib_pipeline_run_3_stage                           \
421               (1,                                               \
422                tm,                                              \
423                test_vhash_gather_keys_mod_stage_##N_KEY_U32,    \
424                test_vhash_hash_finalize_mod_stage_##N_KEY_U32,  \
425                test_vhash_unset_mod_stage_##N_KEY_U32);         \
426         break;
427
428       _ (1);
429       _ (2);
430       _ (3);
431
432 #undef _
433
434 #define _(N_KEY_U32)                                            \
435         case N_KEY_U32:                                         \
436           if (op == GET)                                        \
437             clib_pipeline_run_4_stage                           \
438               (1,                                               \
439                tm,                                              \
440                test_vhash_gather_keys_mod_stage_##N_KEY_U32,    \
441                test_vhash_hash_mix_mod_stage_##N_KEY_U32,       \
442                test_vhash_hash_finalize_mod_stage_##N_KEY_U32,  \
443                test_vhash_get_mod_stage_##N_KEY_U32);           \
444           else if (op == SET)                                   \
445             clib_pipeline_run_4_stage                           \
446               (1,                                               \
447                tm,                                              \
448                test_vhash_gather_keys_mod_stage_##N_KEY_U32,    \
449                test_vhash_hash_mix_mod_stage_##N_KEY_U32,       \
450                test_vhash_hash_finalize_mod_stage_##N_KEY_U32,  \
451                test_vhash_set_mod_stage_##N_KEY_U32);           \
452           else                                                  \
453             clib_pipeline_run_4_stage                           \
454               (1,                                               \
455                tm,                                              \
456                test_vhash_gather_keys_mod_stage_##N_KEY_U32,    \
457                test_vhash_hash_mix_mod_stage_##N_KEY_U32,       \
458                test_vhash_hash_finalize_mod_stage_##N_KEY_U32,  \
459                test_vhash_unset_mod_stage_##N_KEY_U32);         \
460           break;
461
462               _ (4);
463               _ (5);
464               _ (6);
465
466 #undef _
467         }
468     }
469 }
470
471 int test_vhash_main (unformat_input_t * input)
472 {
473   clib_error_t * error = 0;
474   test_vhash_main_t _tm, * tm = &_tm;
475   vhash_t * vh = &tm->vhash;
476   uword i, j;
477
478   memset (tm, 0, sizeof (tm[0]));
479   tm->n_iter = 100;
480   tm->seed = 1;
481   tm->n_keys = 1;
482   tm->n_key_u32 = 1;
483   tm->log2_size = 8;
484   tm->verbose = 0;
485
486   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
487     {
488       if (unformat (input, "iter %d", &tm->n_iter))
489         ;
490       else if (unformat (input, "seed %d", &tm->seed))
491         ;
492       else if (unformat (input, "n-keys %d", &tm->n_keys))
493         ;
494       else if (unformat (input, "log2-size %d", &tm->log2_size))
495         ;
496       else if (unformat (input, "key-words %d", &tm->n_key_u32))
497         ;
498       else if (unformat (input, "verbose %=", &tm->verbose, 1))
499         ;
500       else
501         {
502           error = clib_error_create ("unknown input `%U'\n",
503                                      format_unformat_error, input);
504           goto done;
505         }
506     }
507
508   if (tm->seed == 0)
509     tm->seed = random_default_seed ();
510
511   clib_warning ("iter %d seed %d n-keys %d log2-size %d key-words %d",
512                 tm->n_iter, tm->seed, tm->n_keys, tm->log2_size, tm->n_key_u32);
513
514   {
515     u32 seeds[3];
516     seeds[0] = seeds[1] = seeds[2] = 0xdeadbeef;
517     vhash_init (vh, tm->log2_size, tm->n_key_u32, seeds);
518   }
519
520   /* Choose unique keys. */
521   vec_resize (tm->keys, tm->n_keys * tm->n_key_u32);
522   vec_resize (tm->key_hash, tm->n_key_u32);
523   for (i = j = 0; i < vec_len (tm->keys); i++, j++)
524     {
525       j = j == tm->n_key_u32 ? 0 : j;
526       do {
527         tm->keys[i] = random_u32 (&tm->seed);
528       } while (hash_get (tm->key_hash[j], tm->keys[i]));
529       hash_set (tm->key_hash[j], tm->keys[i], 0);
530     }
531
532   vec_resize (tm->results, tm->n_keys);
533   for (i = 0; i < vec_len (tm->results); i++)
534     {
535       do {
536         tm->results[i] = random_u32 (&tm->seed);
537       } while (tm->results[i] == ~0);
538     }
539
540   vec_resize_aligned (tm->vhash_get_results, tm->n_keys, CLIB_CACHE_LINE_BYTES);
541   vec_clone (tm->vhash_get_key_indices, tm->results);
542   for (i = 0; i < vec_len (tm->vhash_get_key_indices); i++)
543     tm->vhash_get_key_indices[i] = i;
544
545   {
546     uword * is_set_bitmap = 0;
547     uword * to_set_bitmap = 0;
548     uword * to_unset_bitmap = 0;
549     u32 * to_set = 0, * to_unset = 0;
550     u32 * to_set_results = 0, * to_unset_results = 0;
551     u64 t[2];
552
553     for (i = 0; i < tm->n_iter; i++)
554       {
555         vec_reset_length (to_set);
556         vec_reset_length (to_unset);
557         vec_reset_length (to_set_results);
558         vec_reset_length (to_unset_results);
559
560         do {
561           to_set_bitmap = clib_bitmap_random (to_set_bitmap,
562                                               tm->n_keys, &tm->seed);
563         } while (clib_bitmap_is_zero (to_set_bitmap));
564         to_unset_bitmap = clib_bitmap_dup_and (to_set_bitmap, is_set_bitmap);
565         to_set_bitmap = clib_bitmap_andnot (to_set_bitmap, to_unset_bitmap);
566
567         clib_bitmap_foreach (j, to_set_bitmap, ({
568               vec_add1 (to_set, j);
569               vec_add1 (to_set_results, tm->results[j]);
570         }));
571         clib_bitmap_foreach (j, to_unset_bitmap, ({
572               vec_add1 (to_unset, j);
573               vec_add1 (to_unset_results, 0xdeadbeef);
574         }));
575
576         if (vec_len (to_set) > 0)
577           {
578             t[0] = clib_cpu_time_now ();
579             test_vhash_op (tm, to_set, to_set_results,
580                            vec_len (to_set),
581                            SET);
582             t[1] = clib_cpu_time_now ();
583             tm->set_stats.n_clocks += t[1] - t[0];
584             tm->set_stats.n_vectors += vec_len (to_set);
585             tm->set_stats.n_calls += 1;
586             is_set_bitmap = clib_bitmap_or (is_set_bitmap, to_set_bitmap);
587           }
588
589         t[0] = clib_cpu_time_now ();
590         test_vhash_op (tm, tm->vhash_get_key_indices,
591                        tm->vhash_get_results,
592                        vec_len (tm->vhash_get_key_indices),
593                        GET);
594         t[1] = clib_cpu_time_now ();
595         tm->get_stats.n_clocks += t[1] - t[0];
596         tm->get_stats.n_vectors += vec_len (tm->vhash_get_key_indices);
597         tm->get_stats.n_calls += 1;
598
599         for (j = 0; j < vec_len (tm->vhash_get_results); j++)
600           {
601             u32 r0 = tm->vhash_get_results[j];
602             u32 r1 = tm->results[j];
603             if (clib_bitmap_get (is_set_bitmap, j))
604               {
605                 if (r0 != r1)
606                   os_panic ();
607               }
608             else
609               {
610                 if (r0 != ~0)
611                   os_panic ();
612               }
613           }
614
615         if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap))
616           os_panic ();
617
618         if (vec_len (to_unset) > 0)
619           {
620             t[0] = clib_cpu_time_now ();
621             test_vhash_op (tm, to_unset, to_unset_results,
622                            vec_len (to_unset),
623                            UNSET);
624             t[1] = clib_cpu_time_now ();
625             tm->unset_stats.n_clocks += t[1] - t[0];
626             tm->unset_stats.n_vectors += vec_len (to_unset);
627             tm->unset_stats.n_calls += 1;
628             is_set_bitmap = clib_bitmap_andnot (is_set_bitmap, to_unset_bitmap);
629           }
630
631         t[0] = clib_cpu_time_now ();
632         test_vhash_op (tm, tm->vhash_get_key_indices,
633                        tm->vhash_get_results,
634                        vec_len (tm->vhash_get_key_indices),
635                        GET);
636         t[1] = clib_cpu_time_now ();
637         tm->get_stats.n_clocks += t[1] - t[0];
638         tm->get_stats.n_vectors += vec_len (tm->vhash_get_key_indices);
639         tm->get_stats.n_calls += 1;
640
641         for (j = 0; j < vec_len (tm->vhash_get_results); j++)
642           {
643             u32 r0 = tm->vhash_get_results[j];
644             u32 r1 = tm->results[j];
645             if (clib_bitmap_get (is_set_bitmap, j))
646               {
647                 if (r0 != r1)
648                   os_panic ();
649               }
650             else
651               {
652                 if (r0 != ~0)
653                   os_panic ();
654               }
655           }
656
657         if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap))
658           os_panic ();
659       }
660
661     vhash_resize (vh, tm->log2_size + 1);
662
663     test_vhash_op (tm, tm->vhash_get_key_indices,
664                    tm->vhash_get_results,
665                    vec_len (tm->vhash_get_key_indices),
666                    GET);
667
668     for (j = 0; j < vec_len (tm->vhash_get_results); j++)
669       {
670         u32 r0 = tm->vhash_get_results[j];
671         u32 r1 = tm->results[j];
672         if (clib_bitmap_get (is_set_bitmap, j))
673           {
674             if (r0 != r1)
675               os_panic ();
676           }
677         else
678           {
679             if (r0 != ~0)
680               os_panic ();
681           }
682       }
683
684     if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap))
685       os_panic ();
686   }
687
688   {
689     clib_time_t ct;
690
691     clib_time_init (&ct);
692
693     clib_warning ("%.4e clocks/get %.4e gets/call %.4e gets/sec",
694                   (f64) tm->get_stats.n_clocks / (f64) tm->get_stats.n_vectors,
695                   (f64) tm->get_stats.n_vectors / (f64) tm->get_stats.n_calls,
696                   (f64) tm->get_stats.n_vectors / (f64) (tm->get_stats.n_clocks * ct.seconds_per_clock));
697     if (tm->set_stats.n_calls > 0)
698       clib_warning ("%.4e clocks/set %.4e sets/call %.4e sets/sec",
699                     (f64) tm->set_stats.n_clocks / (f64) tm->set_stats.n_vectors,
700                     (f64) tm->set_stats.n_vectors / (f64) tm->set_stats.n_calls,
701                     (f64) tm->set_stats.n_vectors / (f64) (tm->set_stats.n_clocks * ct.seconds_per_clock));
702     if (tm->unset_stats.n_calls > 0)
703       clib_warning ("%.4e clocks/unset %.4e unsets/call %.4e unsets/sec",
704                     (f64) tm->unset_stats.n_clocks / (f64) tm->unset_stats.n_vectors,
705                     (f64) tm->unset_stats.n_vectors / (f64) tm->unset_stats.n_calls,
706                     (f64) tm->unset_stats.n_vectors / (f64) (tm->unset_stats.n_clocks * ct.seconds_per_clock));
707   }
708
709  done:
710   if (error)
711     clib_error_report (error);
712   return 0;
713 }
714
715 #endif /* CLIB_HAVE_VEC128 */
716
717 #ifndef CLIB_HAVE_VEC128
718 int test_vhash_main (unformat_input_t * input)
719 {
720   clib_error ("compiled without vector support");
721   return 0;
722 }
723 #endif
724
725 #ifdef CLIB_UNIX
726 int main (int argc, char * argv [])
727 {
728   unformat_input_t i;
729   int r;
730
731   unformat_init_command_line (&i, argv);
732   r = test_vhash_main (&i);
733   unformat_free (&i);
734   return r;
735 }
736 #endif