053d093524
Type: improvement Signed-off-by: Dave Barach <dave@barachs.net> Change-Id: Id28299a188feefa1899d835fd499f018af95d81b
760 lines
20 KiB
C
760 lines
20 KiB
C
/*
|
|
* Copyright (c) 2015 Cisco and/or its affiliates.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
/*
|
|
Copyright (c) 2010 Eliot Dresselhaus
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
a copy of this software and associated documentation files (the
|
|
"Software"), to deal in the Software without restriction, including
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be
|
|
included in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#if 0
|
|
#ifdef __OPTIMIZE__
|
|
#undef CLIB_DEBUG
|
|
#endif
|
|
#endif
|
|
|
|
#include <vppinfra/bitmap.h>
|
|
#include <vppinfra/error.h>
|
|
#include <vppinfra/os.h>
|
|
#include <vppinfra/random.h>
|
|
#include <vppinfra/time.h>
|
|
#include <vppinfra/vhash.h>
|
|
|
|
#ifdef CLIB_HAVE_VEC128
|
|
|
|
typedef struct
|
|
{
|
|
u32 n_iter;
|
|
u32 seed;
|
|
u32 verbose;
|
|
u32 n_keys;
|
|
u32 log2_size;
|
|
u32 n_key_u32;
|
|
|
|
u32 n_vectors_div_4;
|
|
u32 n_vectors_mod_4;
|
|
|
|
u32 *keys;
|
|
u32 *results;
|
|
|
|
u32 *vhash_get_key_indices;
|
|
u32 *vhash_get_results;
|
|
|
|
u32 *vhash_key_indices;
|
|
u32 *vhash_results;
|
|
|
|
vhash_t vhash;
|
|
|
|
uword **key_hash;
|
|
|
|
struct
|
|
{
|
|
u64 n_clocks;
|
|
u64 n_vectors;
|
|
u64 n_calls;
|
|
} get_stats, set_stats, unset_stats;
|
|
} test_vhash_main_t;
|
|
|
|
always_inline u32
|
|
test_vhash_key_gather (void *_tm, u32 vi, u32 wi, u32 n_key_u32s)
|
|
{
|
|
test_vhash_main_t *tm = _tm;
|
|
ASSERT (n_key_u32s == tm->n_key_u32);
|
|
ASSERT (wi < n_key_u32s);
|
|
vi = vec_elt (tm->vhash_key_indices, vi);
|
|
return vec_elt (tm->keys, vi * n_key_u32s + wi);
|
|
}
|
|
|
|
always_inline u32x4
|
|
test_vhash_4key_gather (void *_tm, u32 vi, u32 wi, u32 n_key_u32s)
|
|
{
|
|
test_vhash_main_t *tm = _tm;
|
|
u32 *p;
|
|
u32x4_union_t x;
|
|
|
|
ASSERT (n_key_u32s == tm->n_key_u32);
|
|
ASSERT (wi < n_key_u32s);
|
|
|
|
p = vec_elt_at_index (tm->vhash_key_indices, vi + 0);
|
|
x.as_u32[0] = tm->keys[p[0] * n_key_u32s + wi];
|
|
x.as_u32[1] = tm->keys[p[1] * n_key_u32s + wi];
|
|
x.as_u32[2] = tm->keys[p[2] * n_key_u32s + wi];
|
|
x.as_u32[3] = tm->keys[p[3] * n_key_u32s + wi];
|
|
return x.as_u32x4;
|
|
}
|
|
|
|
always_inline u32
|
|
test_vhash_get_result (void *_tm,
|
|
u32 vector_index, u32 result_index, u32 n_key_u32s)
|
|
{
|
|
test_vhash_main_t *tm = _tm;
|
|
u32 *p = vec_elt_at_index (tm->vhash_results, vector_index);
|
|
p[0] = result_index;
|
|
return result_index;
|
|
}
|
|
|
|
always_inline u32x4
|
|
test_vhash_get_4result (void *_tm,
|
|
u32 vector_index, u32x4 results, u32 n_key_u32s)
|
|
{
|
|
test_vhash_main_t *tm = _tm;
|
|
u32 *p = vec_elt_at_index (tm->vhash_results, vector_index);
|
|
*(u32x4 *) p = results;
|
|
return results;
|
|
}
|
|
|
|
always_inline u32
|
|
test_vhash_set_result (void *_tm,
|
|
u32 vector_index, u32 old_result, u32 n_key_u32s)
|
|
{
|
|
test_vhash_main_t *tm = _tm;
|
|
u32 *p = vec_elt_at_index (tm->vhash_results, vector_index);
|
|
u32 new_result = p[0];
|
|
p[0] = old_result;
|
|
return new_result;
|
|
}
|
|
|
|
always_inline u32
|
|
test_vhash_unset_result (void *_tm, u32 i, u32 old_result, u32 n_key_u32s)
|
|
{
|
|
test_vhash_main_t *tm = _tm;
|
|
u32 *p = vec_elt_at_index (tm->vhash_results, i);
|
|
p[0] = old_result;
|
|
return 0;
|
|
}
|
|
|
|
#define _(N_KEY_U32) \
|
|
always_inline u32 \
|
|
test_vhash_key_gather_##N_KEY_U32 (void * _tm, u32 vi, u32 i) \
|
|
{ return test_vhash_key_gather (_tm, vi, i, N_KEY_U32); } \
|
|
\
|
|
always_inline u32x4 \
|
|
test_vhash_key_gather_4_##N_KEY_U32 (void * _tm, u32 vi, u32 i) \
|
|
{ return test_vhash_4key_gather (_tm, vi, i, N_KEY_U32); } \
|
|
\
|
|
clib_pipeline_stage \
|
|
(test_vhash_gather_keys_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_gather_4key_stage \
|
|
(&tm->vhash, \
|
|
/* vector_index */ i, \
|
|
test_vhash_key_gather_4_##N_KEY_U32, \
|
|
tm, \
|
|
N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage_no_inline \
|
|
(test_vhash_gather_keys_mod_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_gather_key_stage \
|
|
(&tm->vhash, \
|
|
/* vector_index */ tm->n_vectors_div_4, \
|
|
/* n_vectors */ tm->n_vectors_mod_4, \
|
|
test_vhash_key_gather_##N_KEY_U32, \
|
|
tm, \
|
|
N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage \
|
|
(test_vhash_hash_finalize_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_finalize_stage (&tm->vhash, i, N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage_no_inline \
|
|
(test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_finalize_stage (&tm->vhash, tm->n_vectors_div_4, N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage \
|
|
(test_vhash_get_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_get_4_stage (&tm->vhash, \
|
|
/* vector_index */ i, \
|
|
test_vhash_get_4result, \
|
|
tm, N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage_no_inline \
|
|
(test_vhash_get_mod_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_get_stage (&tm->vhash, \
|
|
/* vector_index */ tm->n_vectors_div_4, \
|
|
/* n_vectors */ tm->n_vectors_mod_4, \
|
|
test_vhash_get_result, \
|
|
tm, N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage \
|
|
(test_vhash_set_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_set_stage (&tm->vhash, \
|
|
/* vector_index */ i, \
|
|
/* n_vectors */ VECTOR_WORD_TYPE_LEN (u32), \
|
|
test_vhash_set_result, \
|
|
tm, N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage_no_inline \
|
|
(test_vhash_set_mod_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_set_stage (&tm->vhash, \
|
|
/* vector_index */ tm->n_vectors_div_4, \
|
|
/* n_vectors */ tm->n_vectors_mod_4, \
|
|
test_vhash_set_result, \
|
|
tm, N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage \
|
|
(test_vhash_unset_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_unset_stage (&tm->vhash, \
|
|
/* vector_index */ i, \
|
|
/* n_vectors */ VECTOR_WORD_TYPE_LEN (u32), \
|
|
test_vhash_unset_result, \
|
|
tm, N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage_no_inline \
|
|
(test_vhash_unset_mod_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_unset_stage (&tm->vhash, \
|
|
/* vector_index */ tm->n_vectors_div_4, \
|
|
/* n_vectors */ tm->n_vectors_mod_4, \
|
|
test_vhash_unset_result, \
|
|
tm, N_KEY_U32); \
|
|
})
|
|
|
|
_(1);
|
|
_(2);
|
|
_(3);
|
|
_(4);
|
|
_(5);
|
|
_(6);
|
|
|
|
#undef _
|
|
|
|
#define _(N_KEY_U32) \
|
|
clib_pipeline_stage \
|
|
(test_vhash_hash_mix_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_mix_stage (&tm->vhash, i, N_KEY_U32); \
|
|
}) \
|
|
\
|
|
clib_pipeline_stage_no_inline \
|
|
(test_vhash_hash_mix_mod_stage_##N_KEY_U32, \
|
|
test_vhash_main_t *, tm, i, \
|
|
{ \
|
|
vhash_mix_stage (&tm->vhash, tm->n_vectors_div_4, N_KEY_U32); \
|
|
})
|
|
|
|
_(4);
|
|
_(5);
|
|
_(6);
|
|
|
|
#undef _
|
|
|
|
typedef enum
|
|
{
|
|
GET, SET, UNSET,
|
|
} test_vhash_op_t;
|
|
|
|
static void
|
|
test_vhash_op (test_vhash_main_t * tm,
|
|
u32 * key_indices,
|
|
u32 * results, uword n_keys, test_vhash_op_t op)
|
|
{
|
|
vhash_validate_sizes (&tm->vhash, tm->n_key_u32, n_keys);
|
|
|
|
tm->vhash_results = results;
|
|
tm->vhash_key_indices = key_indices;
|
|
tm->n_vectors_div_4 = n_keys / 4;
|
|
tm->n_vectors_mod_4 = n_keys % 4;
|
|
|
|
if (tm->n_vectors_div_4 > 0)
|
|
{
|
|
switch (tm->n_key_u32)
|
|
{
|
|
default:
|
|
ASSERT (0);
|
|
break;
|
|
|
|
#define _(N_KEY_U32) \
|
|
case N_KEY_U32: \
|
|
if (op == GET) \
|
|
clib_pipeline_run_3_stage \
|
|
(tm->n_vectors_div_4, \
|
|
tm, \
|
|
test_vhash_gather_keys_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_stage_##N_KEY_U32, \
|
|
test_vhash_get_stage_##N_KEY_U32); \
|
|
else if (op == SET) \
|
|
clib_pipeline_run_3_stage \
|
|
(tm->n_vectors_div_4, \
|
|
tm, \
|
|
test_vhash_gather_keys_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_stage_##N_KEY_U32, \
|
|
test_vhash_set_stage_##N_KEY_U32); \
|
|
else \
|
|
clib_pipeline_run_3_stage \
|
|
(tm->n_vectors_div_4, \
|
|
tm, \
|
|
test_vhash_gather_keys_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_stage_##N_KEY_U32, \
|
|
test_vhash_unset_stage_##N_KEY_U32); \
|
|
break;
|
|
|
|
_(1);
|
|
_(2);
|
|
_(3);
|
|
|
|
#undef _
|
|
|
|
#define _(N_KEY_U32) \
|
|
case N_KEY_U32: \
|
|
if (op == GET) \
|
|
clib_pipeline_run_4_stage \
|
|
(tm->n_vectors_div_4, \
|
|
tm, \
|
|
test_vhash_gather_keys_stage_##N_KEY_U32, \
|
|
test_vhash_hash_mix_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_stage_##N_KEY_U32, \
|
|
test_vhash_get_stage_##N_KEY_U32); \
|
|
else if (op == SET) \
|
|
clib_pipeline_run_4_stage \
|
|
(tm->n_vectors_div_4, \
|
|
tm, \
|
|
test_vhash_gather_keys_stage_##N_KEY_U32, \
|
|
test_vhash_hash_mix_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_stage_##N_KEY_U32, \
|
|
test_vhash_set_stage_##N_KEY_U32); \
|
|
else \
|
|
clib_pipeline_run_4_stage \
|
|
(tm->n_vectors_div_4, \
|
|
tm, \
|
|
test_vhash_gather_keys_stage_##N_KEY_U32, \
|
|
test_vhash_hash_mix_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_stage_##N_KEY_U32, \
|
|
test_vhash_unset_stage_##N_KEY_U32); \
|
|
break;
|
|
|
|
_(4);
|
|
_(5);
|
|
_(6);
|
|
|
|
#undef _
|
|
}
|
|
}
|
|
|
|
|
|
if (tm->n_vectors_mod_4 > 0)
|
|
{
|
|
switch (tm->n_key_u32)
|
|
{
|
|
default:
|
|
ASSERT (0);
|
|
break;
|
|
|
|
#define _(N_KEY_U32) \
|
|
case N_KEY_U32: \
|
|
if (op == GET) \
|
|
clib_pipeline_run_3_stage \
|
|
(1, \
|
|
tm, \
|
|
test_vhash_gather_keys_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \
|
|
test_vhash_get_mod_stage_##N_KEY_U32); \
|
|
else if (op == SET) \
|
|
clib_pipeline_run_3_stage \
|
|
(1, \
|
|
tm, \
|
|
test_vhash_gather_keys_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \
|
|
test_vhash_set_mod_stage_##N_KEY_U32); \
|
|
else \
|
|
clib_pipeline_run_3_stage \
|
|
(1, \
|
|
tm, \
|
|
test_vhash_gather_keys_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \
|
|
test_vhash_unset_mod_stage_##N_KEY_U32); \
|
|
break;
|
|
|
|
_(1);
|
|
_(2);
|
|
_(3);
|
|
|
|
#undef _
|
|
|
|
#define _(N_KEY_U32) \
|
|
case N_KEY_U32: \
|
|
if (op == GET) \
|
|
clib_pipeline_run_4_stage \
|
|
(1, \
|
|
tm, \
|
|
test_vhash_gather_keys_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_mix_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \
|
|
test_vhash_get_mod_stage_##N_KEY_U32); \
|
|
else if (op == SET) \
|
|
clib_pipeline_run_4_stage \
|
|
(1, \
|
|
tm, \
|
|
test_vhash_gather_keys_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_mix_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \
|
|
test_vhash_set_mod_stage_##N_KEY_U32); \
|
|
else \
|
|
clib_pipeline_run_4_stage \
|
|
(1, \
|
|
tm, \
|
|
test_vhash_gather_keys_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_mix_mod_stage_##N_KEY_U32, \
|
|
test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \
|
|
test_vhash_unset_mod_stage_##N_KEY_U32); \
|
|
break;
|
|
|
|
_(4);
|
|
_(5);
|
|
_(6);
|
|
|
|
#undef _
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
test_vhash_main (unformat_input_t * input)
|
|
{
|
|
clib_error_t *error = 0;
|
|
test_vhash_main_t _tm, *tm = &_tm;
|
|
vhash_t *vh = &tm->vhash;
|
|
uword i, j;
|
|
|
|
clib_memset (tm, 0, sizeof (tm[0]));
|
|
tm->n_iter = 100;
|
|
tm->seed = 1;
|
|
tm->n_keys = 1;
|
|
tm->n_key_u32 = 1;
|
|
tm->log2_size = 8;
|
|
tm->verbose = 0;
|
|
|
|
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
|
{
|
|
if (unformat (input, "iter %d", &tm->n_iter))
|
|
;
|
|
else if (unformat (input, "seed %d", &tm->seed))
|
|
;
|
|
else if (unformat (input, "n-keys %d", &tm->n_keys))
|
|
;
|
|
else if (unformat (input, "log2-size %d", &tm->log2_size))
|
|
;
|
|
else if (unformat (input, "key-words %d", &tm->n_key_u32))
|
|
;
|
|
else if (unformat (input, "verbose %=", &tm->verbose, 1))
|
|
;
|
|
else
|
|
{
|
|
error = clib_error_create ("unknown input `%U'\n",
|
|
format_unformat_error, input);
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (tm->seed == 0)
|
|
tm->seed = random_default_seed ();
|
|
|
|
clib_warning ("iter %d seed %d n-keys %d log2-size %d key-words %d",
|
|
tm->n_iter, tm->seed, tm->n_keys, tm->log2_size,
|
|
tm->n_key_u32);
|
|
|
|
{
|
|
u32 seeds[3];
|
|
seeds[0] = seeds[1] = seeds[2] = 0xdeadbeef;
|
|
vhash_init (vh, tm->log2_size, tm->n_key_u32, seeds);
|
|
}
|
|
|
|
/* Choose unique keys. */
|
|
vec_resize (tm->keys, tm->n_keys * tm->n_key_u32);
|
|
vec_resize (tm->key_hash, tm->n_key_u32);
|
|
for (i = j = 0; i < vec_len (tm->keys); i++, j++)
|
|
{
|
|
j = j == tm->n_key_u32 ? 0 : j;
|
|
do
|
|
{
|
|
tm->keys[i] = random_u32 (&tm->seed);
|
|
}
|
|
while (hash_get (tm->key_hash[j], tm->keys[i]));
|
|
hash_set (tm->key_hash[j], tm->keys[i], 0);
|
|
}
|
|
|
|
vec_resize (tm->results, tm->n_keys);
|
|
for (i = 0; i < vec_len (tm->results); i++)
|
|
{
|
|
do
|
|
{
|
|
tm->results[i] = random_u32 (&tm->seed);
|
|
}
|
|
while (tm->results[i] == ~0);
|
|
}
|
|
|
|
vec_resize_aligned (tm->vhash_get_results, tm->n_keys,
|
|
CLIB_CACHE_LINE_BYTES);
|
|
vec_clone (tm->vhash_get_key_indices, tm->results);
|
|
for (i = 0; i < vec_len (tm->vhash_get_key_indices); i++)
|
|
tm->vhash_get_key_indices[i] = i;
|
|
|
|
{
|
|
uword *is_set_bitmap = 0;
|
|
uword *to_set_bitmap = 0;
|
|
uword *to_unset_bitmap = 0;
|
|
u32 *to_set = 0, *to_unset = 0;
|
|
u32 *to_set_results = 0, *to_unset_results = 0;
|
|
u64 t[2];
|
|
|
|
for (i = 0; i < tm->n_iter; i++)
|
|
{
|
|
vec_reset_length (to_set);
|
|
vec_reset_length (to_unset);
|
|
vec_reset_length (to_set_results);
|
|
vec_reset_length (to_unset_results);
|
|
|
|
do
|
|
{
|
|
to_set_bitmap = clib_bitmap_random (to_set_bitmap,
|
|
tm->n_keys, &tm->seed);
|
|
}
|
|
while (clib_bitmap_is_zero (to_set_bitmap));
|
|
to_unset_bitmap = clib_bitmap_dup_and (to_set_bitmap, is_set_bitmap);
|
|
to_set_bitmap = clib_bitmap_andnot (to_set_bitmap, to_unset_bitmap);
|
|
|
|
/* *INDENT-OFF* */
|
|
clib_bitmap_foreach (j, to_set_bitmap, ({
|
|
vec_add1 (to_set, j);
|
|
vec_add1 (to_set_results, tm->results[j]);
|
|
}));
|
|
/* *INDENT-ON* */
|
|
/* *INDENT-OFF* */
|
|
clib_bitmap_foreach (j, to_unset_bitmap, ({
|
|
vec_add1 (to_unset, j);
|
|
vec_add1 (to_unset_results, 0xdeadbeef);
|
|
}));
|
|
/* *INDENT-ON* */
|
|
|
|
if (vec_len (to_set) > 0)
|
|
{
|
|
t[0] = clib_cpu_time_now ();
|
|
test_vhash_op (tm, to_set, to_set_results, vec_len (to_set), SET);
|
|
t[1] = clib_cpu_time_now ();
|
|
tm->set_stats.n_clocks += t[1] - t[0];
|
|
tm->set_stats.n_vectors += vec_len (to_set);
|
|
tm->set_stats.n_calls += 1;
|
|
is_set_bitmap = clib_bitmap_or (is_set_bitmap, to_set_bitmap);
|
|
}
|
|
|
|
t[0] = clib_cpu_time_now ();
|
|
test_vhash_op (tm, tm->vhash_get_key_indices,
|
|
tm->vhash_get_results,
|
|
vec_len (tm->vhash_get_key_indices), GET);
|
|
t[1] = clib_cpu_time_now ();
|
|
tm->get_stats.n_clocks += t[1] - t[0];
|
|
tm->get_stats.n_vectors += vec_len (tm->vhash_get_key_indices);
|
|
tm->get_stats.n_calls += 1;
|
|
|
|
for (j = 0; j < vec_len (tm->vhash_get_results); j++)
|
|
{
|
|
u32 r0 = tm->vhash_get_results[j];
|
|
u32 r1 = tm->results[j];
|
|
if (clib_bitmap_get (is_set_bitmap, j))
|
|
{
|
|
if (r0 != r1)
|
|
os_panic ();
|
|
}
|
|
else
|
|
{
|
|
if (r0 != ~0)
|
|
os_panic ();
|
|
}
|
|
}
|
|
|
|
if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap))
|
|
os_panic ();
|
|
|
|
if (vec_len (to_unset) > 0)
|
|
{
|
|
t[0] = clib_cpu_time_now ();
|
|
test_vhash_op (tm, to_unset, to_unset_results,
|
|
vec_len (to_unset), UNSET);
|
|
t[1] = clib_cpu_time_now ();
|
|
tm->unset_stats.n_clocks += t[1] - t[0];
|
|
tm->unset_stats.n_vectors += vec_len (to_unset);
|
|
tm->unset_stats.n_calls += 1;
|
|
is_set_bitmap =
|
|
clib_bitmap_andnot (is_set_bitmap, to_unset_bitmap);
|
|
}
|
|
|
|
t[0] = clib_cpu_time_now ();
|
|
test_vhash_op (tm, tm->vhash_get_key_indices,
|
|
tm->vhash_get_results,
|
|
vec_len (tm->vhash_get_key_indices), GET);
|
|
t[1] = clib_cpu_time_now ();
|
|
tm->get_stats.n_clocks += t[1] - t[0];
|
|
tm->get_stats.n_vectors += vec_len (tm->vhash_get_key_indices);
|
|
tm->get_stats.n_calls += 1;
|
|
|
|
for (j = 0; j < vec_len (tm->vhash_get_results); j++)
|
|
{
|
|
u32 r0 = tm->vhash_get_results[j];
|
|
u32 r1 = tm->results[j];
|
|
if (clib_bitmap_get (is_set_bitmap, j))
|
|
{
|
|
if (r0 != r1)
|
|
os_panic ();
|
|
}
|
|
else
|
|
{
|
|
if (r0 != ~0)
|
|
os_panic ();
|
|
}
|
|
}
|
|
|
|
if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap))
|
|
os_panic ();
|
|
}
|
|
|
|
vhash_resize (vh, tm->log2_size + 1);
|
|
|
|
test_vhash_op (tm, tm->vhash_get_key_indices,
|
|
tm->vhash_get_results,
|
|
vec_len (tm->vhash_get_key_indices), GET);
|
|
|
|
for (j = 0; j < vec_len (tm->vhash_get_results); j++)
|
|
{
|
|
u32 r0 = tm->vhash_get_results[j];
|
|
u32 r1 = tm->results[j];
|
|
if (clib_bitmap_get (is_set_bitmap, j))
|
|
{
|
|
if (r0 != r1)
|
|
os_panic ();
|
|
}
|
|
else
|
|
{
|
|
if (r0 != ~0)
|
|
os_panic ();
|
|
}
|
|
}
|
|
|
|
if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap))
|
|
os_panic ();
|
|
}
|
|
|
|
{
|
|
clib_time_t ct;
|
|
|
|
clib_time_init (&ct);
|
|
|
|
clib_warning ("%.4e clocks/get %.4e gets/call %.4e gets/sec",
|
|
(f64) tm->get_stats.n_clocks /
|
|
(f64) tm->get_stats.n_vectors,
|
|
(f64) tm->get_stats.n_vectors / (f64) tm->get_stats.n_calls,
|
|
(f64) tm->get_stats.n_vectors /
|
|
(f64) (tm->get_stats.n_clocks * ct.seconds_per_clock));
|
|
if (tm->set_stats.n_calls > 0)
|
|
clib_warning ("%.4e clocks/set %.4e sets/call %.4e sets/sec",
|
|
(f64) tm->set_stats.n_clocks /
|
|
(f64) tm->set_stats.n_vectors,
|
|
(f64) tm->set_stats.n_vectors /
|
|
(f64) tm->set_stats.n_calls,
|
|
(f64) tm->set_stats.n_vectors /
|
|
(f64) (tm->set_stats.n_clocks * ct.seconds_per_clock));
|
|
if (tm->unset_stats.n_calls > 0)
|
|
clib_warning ("%.4e clocks/unset %.4e unsets/call %.4e unsets/sec",
|
|
(f64) tm->unset_stats.n_clocks /
|
|
(f64) tm->unset_stats.n_vectors,
|
|
(f64) tm->unset_stats.n_vectors /
|
|
(f64) tm->unset_stats.n_calls,
|
|
(f64) tm->unset_stats.n_vectors /
|
|
(f64) (tm->unset_stats.n_clocks * ct.seconds_per_clock));
|
|
}
|
|
|
|
done:
|
|
if (error)
|
|
clib_error_report (error);
|
|
return 0;
|
|
}
|
|
|
|
#endif /* CLIB_HAVE_VEC128 */
|
|
|
|
#ifndef CLIB_HAVE_VEC128
|
|
int
|
|
test_vhash_main (unformat_input_t * input)
|
|
{
|
|
clib_error ("compiled without vector support");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CLIB_UNIX
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
unformat_input_t i;
|
|
int r;
|
|
|
|
clib_mem_init (0, 64ULL << 20);
|
|
|
|
unformat_init_command_line (&i, argv);
|
|
r = test_vhash_main (&i);
|
|
unformat_free (&i);
|
|
return r;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* fd.io coding-style-patch-verification: ON
|
|
*
|
|
* Local Variables:
|
|
* eval: (c-set-style "gnu")
|
|
* End:
|
|
*/
|