LCOV - code coverage report
Current view: top level - app/test - test_hash_perf.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 1 256 0.4 %
Date: 2025-02-01 18:54:23 Functions: 1 11 9.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 204 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2015 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdio.h>
       6                 :            : #include <inttypes.h>
       7                 :            : 
       8                 :            : #include <rte_lcore.h>
       9                 :            : #include <rte_cycles.h>
      10                 :            : #include <rte_malloc.h>
      11                 :            : #include <rte_hash.h>
      12                 :            : #include <rte_hash_crc.h>
      13                 :            : #include <rte_jhash.h>
      14                 :            : #include <rte_fbk_hash.h>
      15                 :            : #include <rte_random.h>
      16                 :            : #include <rte_string_fns.h>
      17                 :            : 
      18                 :            : #include "test.h"
      19                 :            : 
      20                 :            : #define MAX_ENTRIES (1 << 19)
      21                 :            : #define KEYS_TO_ADD (MAX_ENTRIES)
      22                 :            : #define ADD_PERCENT 0.75 /* 75% table utilization */
      23                 :            : #define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */
      24                 :            : /* BUCKET_SIZE should be same as RTE_HASH_BUCKET_ENTRIES in rte_hash library */
      25                 :            : #define BUCKET_SIZE 8
      26                 :            : #define NUM_BUCKETS (MAX_ENTRIES / BUCKET_SIZE)
      27                 :            : #define MAX_KEYSIZE 64
      28                 :            : #define NUM_KEYSIZES 10
      29                 :            : #define NUM_SHUFFLES 10
      30                 :            : #define BURST_SIZE 16
      31                 :            : 
      32                 :            : enum operations {
      33                 :            :         OP_ADD = 0,
      34                 :            :         OP_LOOKUP,
      35                 :            :         OP_LOOKUP_MULTI,
      36                 :            :         OP_DELETE,
      37                 :            :         NUM_OPERATIONS
      38                 :            : };
      39                 :            : 
      40                 :            : static uint32_t hashtest_key_lens[] = {
      41                 :            :         /* standard key sizes */
      42                 :            :         4, 8, 16, 32, 48, 64,
      43                 :            :         /* IPv4 SRC + DST + protocol, unpadded */
      44                 :            :         9,
      45                 :            :         /* IPv4 5-tuple, unpadded */
      46                 :            :         13,
      47                 :            :         /* IPv6 5-tuple, unpadded */
      48                 :            :         37,
      49                 :            :         /* IPv6 5-tuple, padded to 8-byte boundary */
      50                 :            :         40
      51                 :            : };
      52                 :            : 
      53                 :            : struct rte_hash *h[NUM_KEYSIZES];
      54                 :            : 
      55                 :            : /* Array that stores if a slot is full */
      56                 :            : static uint8_t slot_taken[MAX_ENTRIES];
      57                 :            : 
      58                 :            : /* Array to store number of cycles per operation */
      59                 :            : static uint64_t cycles[NUM_KEYSIZES][NUM_OPERATIONS][2][2];
      60                 :            : 
      61                 :            : /* Array to store all input keys */
      62                 :            : static uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE];
      63                 :            : 
      64                 :            : /* Array to store the precomputed hash for 'keys' */
      65                 :            : static hash_sig_t signatures[KEYS_TO_ADD];
      66                 :            : 
      67                 :            : /* Array to store how many busy entries have each bucket */
      68                 :            : static uint8_t buckets[NUM_BUCKETS];
      69                 :            : 
      70                 :            : /* Array to store the positions where keys are added */
      71                 :            : static int32_t positions[KEYS_TO_ADD];
      72                 :            : 
      73                 :            : /* Parameters used for hash table in unit test functions. */
      74                 :            : static struct rte_hash_parameters ut_params = {
      75                 :            :         .entries = MAX_ENTRIES,
      76                 :            :         .hash_func = rte_jhash,
      77                 :            :         .hash_func_init_val = 0,
      78                 :            : };
      79                 :            : 
      80                 :            : static int
      81                 :          0 : create_table(unsigned int with_data, unsigned int table_index,
      82                 :            :                 unsigned int with_locks, unsigned int ext)
      83                 :            : {
      84                 :            :         char name[RTE_HASH_NAMESIZE];
      85                 :            : 
      86         [ #  # ]:          0 :         if (with_data)
      87                 :            :                 /* Table will store 8-byte data */
      88                 :          0 :                 snprintf(name, sizeof(name), "test_hash%u_data",
      89                 :            :                                 hashtest_key_lens[table_index]);
      90                 :            :         else
      91                 :          0 :                 snprintf(name, sizeof(name), "test_hash%u",
      92                 :            :                                 hashtest_key_lens[table_index]);
      93                 :            : 
      94                 :            : 
      95         [ #  # ]:          0 :         if (with_locks)
      96                 :          0 :                 ut_params.extra_flag =
      97                 :            :                         RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT
      98                 :            :                                 | RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY;
      99                 :            :         else
     100                 :          0 :                 ut_params.extra_flag = 0;
     101                 :            : 
     102         [ #  # ]:          0 :         if (ext)
     103                 :          0 :                 ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
     104                 :            : 
     105                 :          0 :         ut_params.name = name;
     106                 :          0 :         ut_params.key_len = hashtest_key_lens[table_index];
     107                 :          0 :         ut_params.socket_id = rte_socket_id();
     108                 :          0 :         h[table_index] = rte_hash_find_existing(name);
     109                 :          0 :         rte_hash_free(h[table_index]);
     110                 :          0 :         h[table_index] = rte_hash_create(&ut_params);
     111         [ #  # ]:          0 :         if (h[table_index] == NULL) {
     112                 :            :                 printf("Error creating table\n");
     113                 :          0 :                 return -1;
     114                 :            :         }
     115                 :            :         return 0;
     116                 :            : 
     117                 :            : }
     118                 :            : 
     119                 :            : /* Shuffle the keys that have been added, so lookups will be totally random */
     120                 :            : static void
     121                 :          0 : shuffle_input_keys(unsigned int table_index, unsigned int ext)
     122                 :            : {
     123                 :            :         unsigned i;
     124                 :            :         uint32_t swap_idx;
     125                 :            :         uint8_t temp_key[MAX_KEYSIZE];
     126                 :            :         hash_sig_t temp_signature;
     127                 :            :         int32_t temp_position;
     128                 :            :         unsigned int keys_to_add;
     129                 :            : 
     130         [ #  # ]:          0 :         if (!ext)
     131                 :            :                 keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
     132                 :            :         else
     133                 :            :                 keys_to_add = KEYS_TO_ADD;
     134                 :            : 
     135         [ #  # ]:          0 :         for (i = keys_to_add - 1; i > 0; i--) {
     136                 :          0 :                 swap_idx = rte_rand() % i;
     137                 :            : 
     138                 :          0 :                 memcpy(temp_key, keys[i], hashtest_key_lens[table_index]);
     139                 :          0 :                 temp_signature = signatures[i];
     140                 :          0 :                 temp_position = positions[i];
     141                 :            : 
     142                 :          0 :                 memcpy(keys[i], keys[swap_idx], hashtest_key_lens[table_index]);
     143                 :          0 :                 signatures[i] = signatures[swap_idx];
     144                 :          0 :                 positions[i] = positions[swap_idx];
     145                 :            : 
     146                 :            :                 memcpy(keys[swap_idx], temp_key, hashtest_key_lens[table_index]);
     147                 :          0 :                 signatures[swap_idx] = temp_signature;
     148                 :          0 :                 positions[swap_idx] = temp_position;
     149                 :            :         }
     150                 :          0 : }
     151                 :            : 
     152                 :            : /*
     153                 :            :  * Looks for random keys which
     154                 :            :  * ALL can fit in hash table (no errors)
     155                 :            :  */
     156                 :            : static int
     157                 :          0 : get_input_keys(unsigned int with_pushes, unsigned int table_index,
     158                 :            :                                                         unsigned int ext)
     159                 :            : {
     160                 :            :         unsigned i, j;
     161                 :            :         unsigned bucket_idx, incr, success = 1;
     162                 :            :         uint8_t k = 0;
     163                 :            :         int32_t ret;
     164                 :            :         const uint32_t bucket_bitmask = NUM_BUCKETS - 1;
     165                 :            :         unsigned int keys_to_add;
     166                 :            : 
     167         [ #  # ]:          0 :         if (!ext)
     168                 :            :                 keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
     169                 :            :         else
     170                 :            :                 keys_to_add = KEYS_TO_ADD;
     171                 :            :         /* Reset all arrays */
     172         [ #  # ]:          0 :         for (i = 0; i < MAX_ENTRIES; i++)
     173                 :          0 :                 slot_taken[i] = 0;
     174                 :            : 
     175         [ #  # ]:          0 :         for (i = 0; i < NUM_BUCKETS; i++)
     176                 :          0 :                 buckets[i] = 0;
     177                 :            : 
     178         [ #  # ]:          0 :         for (j = 0; j < hashtest_key_lens[table_index]; j++)
     179                 :          0 :                 keys[0][j] = 0;
     180                 :            : 
     181                 :            :         /*
     182                 :            :          * Add only entries that are not duplicated and that fits in the table
     183                 :            :          * (cannot store more than BUCKET_SIZE entries in a bucket).
     184                 :            :          * Regardless a key has been added correctly or not (success),
     185                 :            :          * the next one to try will be increased by 1.
     186                 :            :          */
     187         [ #  # ]:          0 :         for (i = 0; i < keys_to_add;) {
     188                 :            :                 incr = 0;
     189         [ #  # ]:          0 :                 if (i != 0) {
     190                 :          0 :                         keys[i][0] = ++k;
     191                 :            :                         /* Overflow, need to increment the next byte */
     192         [ #  # ]:          0 :                         if (keys[i][0] == 0)
     193                 :            :                                 incr = 1;
     194         [ #  # ]:          0 :                         for (j = 1; j < hashtest_key_lens[table_index]; j++) {
     195                 :            :                                 /* Do not increase next byte */
     196         [ #  # ]:          0 :                                 if (incr == 0)
     197         [ #  # ]:          0 :                                         if (success == 1)
     198                 :          0 :                                                 keys[i][j] = keys[i - 1][j];
     199                 :            :                                         else
     200                 :          0 :                                                 keys[i][j] = keys[i][j];
     201                 :            :                                 /* Increase next byte by one */
     202                 :            :                                 else {
     203         [ #  # ]:          0 :                                         if (success == 1)
     204                 :          0 :                                                 keys[i][j] = keys[i-1][j] + 1;
     205                 :            :                                         else
     206                 :          0 :                                                 keys[i][j] = keys[i][j] + 1;
     207         [ #  # ]:          0 :                                         if (keys[i][j] == 0)
     208                 :            :                                                 incr = 1;
     209                 :            :                                         else
     210                 :            :                                                 incr = 0;
     211                 :            :                                 }
     212                 :            :                         }
     213                 :            :                 }
     214                 :            :                 success = 0;
     215                 :          0 :                 signatures[i] = rte_hash_hash(h[table_index], keys[i]);
     216                 :          0 :                 bucket_idx = signatures[i] & bucket_bitmask;
     217                 :            :                 /*
     218                 :            :                  * If we are not inserting keys in secondary location,
     219                 :            :                  * when bucket is full, do not try to insert the key
     220                 :            :                  */
     221         [ #  # ]:          0 :                 if (with_pushes == 0)
     222         [ #  # ]:          0 :                         if (buckets[bucket_idx] == BUCKET_SIZE)
     223                 :          0 :                                 continue;
     224                 :            : 
     225                 :            :                 /* If key can be added, leave in successful key arrays "keys" */
     226                 :          0 :                 ret = rte_hash_add_key_with_hash(h[table_index], keys[i],
     227                 :            :                                                 signatures[i]);
     228         [ #  # ]:          0 :                 if (ret >= 0) {
     229                 :            :                         /* If key is already added, ignore the entry and do not store */
     230         [ #  # ]:          0 :                         if (slot_taken[ret])
     231                 :          0 :                                 continue;
     232                 :            :                         else {
     233                 :            :                                 /* Store the returned position and mark slot as taken */
     234                 :          0 :                                 slot_taken[ret] = 1;
     235                 :          0 :                                 positions[i] = ret;
     236                 :          0 :                                 buckets[bucket_idx]++;
     237                 :            :                                 success = 1;
     238                 :          0 :                                 i++;
     239                 :            :                         }
     240                 :            :                 }
     241                 :            :         }
     242                 :            : 
     243                 :            :         /* Reset the table, so we can measure the time to add all the entries */
     244                 :          0 :         rte_hash_free(h[table_index]);
     245                 :          0 :         h[table_index] = rte_hash_create(&ut_params);
     246                 :            : 
     247                 :          0 :         return 0;
     248                 :            : }
     249                 :            : 
     250                 :            : static int
     251                 :          0 : timed_adds(unsigned int with_hash, unsigned int with_data,
     252                 :            :                                 unsigned int table_index, unsigned int ext)
     253                 :            : {
     254                 :            :         unsigned i;
     255                 :            :         const uint64_t start_tsc = rte_rdtsc();
     256                 :            :         void *data;
     257                 :            :         int32_t ret;
     258                 :            :         unsigned int keys_to_add;
     259         [ #  # ]:          0 :         if (!ext)
     260                 :            :                 keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
     261                 :            :         else
     262                 :            :                 keys_to_add = KEYS_TO_ADD;
     263                 :            : 
     264         [ #  # ]:          0 :         for (i = 0; i < keys_to_add; i++) {
     265                 :          0 :                 data = (void *) ((uintptr_t) signatures[i]);
     266         [ #  # ]:          0 :                 if (with_hash && with_data) {
     267                 :          0 :                         ret = rte_hash_add_key_with_hash_data(h[table_index],
     268                 :          0 :                                                 (const void *) keys[i],
     269                 :            :                                                 signatures[i], data);
     270         [ #  # ]:          0 :                         if (ret < 0) {
     271                 :            :                                 printf("H+D: Failed to add key number %u\n", i);
     272                 :          0 :                                 return -1;
     273                 :            :                         }
     274         [ #  # ]:          0 :                 } else if (with_hash && !with_data) {
     275                 :          0 :                         ret = rte_hash_add_key_with_hash(h[table_index],
     276                 :          0 :                                                 (const void *) keys[i],
     277                 :            :                                                 signatures[i]);
     278         [ #  # ]:          0 :                         if (ret >= 0)
     279                 :          0 :                                 positions[i] = ret;
     280                 :            :                         else {
     281                 :            :                                 printf("H: Failed to add key number %u\n", i);
     282                 :          0 :                                 return -1;
     283                 :            :                         }
     284         [ #  # ]:          0 :                 } else if (!with_hash && with_data) {
     285                 :          0 :                         ret = rte_hash_add_key_data(h[table_index],
     286                 :          0 :                                                 (const void *) keys[i],
     287                 :            :                                                 data);
     288         [ #  # ]:          0 :                         if (ret < 0) {
     289                 :            :                                 printf("D: Failed to add key number %u\n", i);
     290                 :          0 :                                 return -1;
     291                 :            :                         }
     292                 :            :                 } else {
     293                 :          0 :                         ret = rte_hash_add_key(h[table_index], keys[i]);
     294         [ #  # ]:          0 :                         if (ret >= 0)
     295                 :          0 :                                 positions[i] = ret;
     296                 :            :                         else {
     297                 :            :                                 printf("Failed to add key number %u\n", i);
     298                 :          0 :                                 return -1;
     299                 :            :                         }
     300                 :            :                 }
     301                 :            :         }
     302                 :            : 
     303                 :            :         const uint64_t end_tsc = rte_rdtsc();
     304                 :          0 :         const uint64_t time_taken = end_tsc - start_tsc;
     305                 :            : 
     306                 :          0 :         cycles[table_index][OP_ADD][with_hash][with_data] = time_taken/keys_to_add;
     307                 :            : 
     308                 :          0 :         return 0;
     309                 :            : }
     310                 :            : 
     311                 :            : static int
     312                 :          0 : timed_lookups(unsigned int with_hash, unsigned int with_data,
     313                 :            :                                 unsigned int table_index, unsigned int ext)
     314                 :            : {
     315                 :            :         unsigned i, j;
     316                 :            :         const uint64_t start_tsc = rte_rdtsc();
     317                 :            :         void *ret_data;
     318                 :            :         void *expected_data;
     319                 :            :         int32_t ret;
     320                 :            :         unsigned int keys_to_add, num_lookups;
     321                 :            : 
     322         [ #  # ]:          0 :         if (!ext) {
     323                 :            :                 keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
     324                 :            :                 num_lookups = NUM_LOOKUPS * ADD_PERCENT;
     325                 :            :         } else {
     326                 :            :                 keys_to_add = KEYS_TO_ADD;
     327                 :            :                 num_lookups = NUM_LOOKUPS;
     328                 :            :         }
     329         [ #  # ]:          0 :         for (i = 0; i < num_lookups / keys_to_add; i++) {
     330         [ #  # ]:          0 :                 for (j = 0; j < keys_to_add; j++) {
     331         [ #  # ]:          0 :                         if (with_hash && with_data) {
     332                 :          0 :                                 ret = rte_hash_lookup_with_hash_data(h[table_index],
     333                 :          0 :                                                         (const void *) keys[j],
     334                 :            :                                                         signatures[j], &ret_data);
     335         [ #  # ]:          0 :                                 if (ret < 0) {
     336                 :            :                                         printf("Key number %u was not found\n", j);
     337                 :          0 :                                         return -1;
     338                 :            :                                 }
     339                 :          0 :                                 expected_data = (void *) ((uintptr_t) signatures[j]);
     340         [ #  # ]:          0 :                                 if (ret_data != expected_data) {
     341                 :            :                                         printf("Data returned for key number %u is %p,"
     342                 :            :                                                " but should be %p\n", j, ret_data,
     343                 :            :                                                 expected_data);
     344                 :          0 :                                         return -1;
     345                 :            :                                 }
     346         [ #  # ]:          0 :                         } else if (with_hash && !with_data) {
     347                 :          0 :                                 ret = rte_hash_lookup_with_hash(h[table_index],
     348                 :          0 :                                                         (const void *) keys[j],
     349                 :            :                                                         signatures[j]);
     350   [ #  #  #  # ]:          0 :                                 if (ret < 0 || ret != positions[j]) {
     351                 :          0 :                                         printf("Key looked up in %d, should be in %d\n",
     352                 :            :                                                 ret, positions[j]);
     353                 :          0 :                                         return -1;
     354                 :            :                                 }
     355         [ #  # ]:          0 :                         } else if (!with_hash && with_data) {
     356                 :          0 :                                 ret = rte_hash_lookup_data(h[table_index],
     357                 :          0 :                                                         (const void *) keys[j], &ret_data);
     358         [ #  # ]:          0 :                                 if (ret < 0) {
     359                 :            :                                         printf("Key number %u was not found\n", j);
     360                 :          0 :                                         return -1;
     361                 :            :                                 }
     362                 :          0 :                                 expected_data = (void *) ((uintptr_t) signatures[j]);
     363         [ #  # ]:          0 :                                 if (ret_data != expected_data) {
     364                 :            :                                         printf("Data returned for key number %u is %p,"
     365                 :            :                                                " but should be %p\n", j, ret_data,
     366                 :            :                                                 expected_data);
     367                 :          0 :                                         return -1;
     368                 :            :                                 }
     369                 :            :                         } else {
     370                 :          0 :                                 ret = rte_hash_lookup(h[table_index], keys[j]);
     371   [ #  #  #  # ]:          0 :                                 if (ret < 0 || ret != positions[j]) {
     372                 :          0 :                                         printf("Key looked up in %d, should be in %d\n",
     373                 :            :                                                 ret, positions[j]);
     374                 :          0 :                                         return -1;
     375                 :            :                                 }
     376                 :            :                         }
     377                 :            :                 }
     378                 :            :         }
     379                 :            : 
     380                 :            :         const uint64_t end_tsc = rte_rdtsc();
     381                 :          0 :         const uint64_t time_taken = end_tsc - start_tsc;
     382                 :            : 
     383                 :          0 :         cycles[table_index][OP_LOOKUP][with_hash][with_data] = time_taken/num_lookups;
     384                 :            : 
     385                 :          0 :         return 0;
     386                 :            : }
     387                 :            : 
     388                 :            : static int
     389                 :          0 : timed_lookups_multi(unsigned int with_hash, unsigned int with_data,
     390                 :            :                 unsigned int table_index, unsigned int ext)
     391                 :            : {
     392                 :            :         unsigned i, j, k;
     393                 :            :         int32_t positions_burst[BURST_SIZE];
     394                 :            :         const void *keys_burst[BURST_SIZE];
     395                 :            :         void *expected_data[BURST_SIZE];
     396                 :            :         void *ret_data[BURST_SIZE];
     397                 :            :         uint64_t hit_mask;
     398                 :            :         int ret;
     399                 :            :         unsigned int keys_to_add, num_lookups;
     400                 :            : 
     401         [ #  # ]:          0 :         if (!ext) {
     402                 :            :                 keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
     403                 :            :                 num_lookups = NUM_LOOKUPS * ADD_PERCENT;
     404                 :            :         } else {
     405                 :            :                 keys_to_add = KEYS_TO_ADD;
     406                 :            :                 num_lookups = NUM_LOOKUPS;
     407                 :            :         }
     408                 :            : 
     409                 :            :         const uint64_t start_tsc = rte_rdtsc();
     410                 :            : 
     411         [ #  # ]:          0 :         for (i = 0; i < num_lookups/keys_to_add; i++) {
     412         [ #  # ]:          0 :                 for (j = 0; j < keys_to_add/BURST_SIZE; j++) {
     413         [ #  # ]:          0 :                         for (k = 0; k < BURST_SIZE; k++)
     414                 :          0 :                                 keys_burst[k] = keys[j * BURST_SIZE + k];
     415         [ #  # ]:          0 :                         if (!with_hash && with_data) {
     416                 :          0 :                                 ret = rte_hash_lookup_bulk_data(h[table_index],
     417                 :            :                                         (const void **) keys_burst,
     418                 :            :                                         BURST_SIZE,
     419                 :            :                                         &hit_mask,
     420                 :            :                                         ret_data);
     421         [ #  # ]:          0 :                                 if (ret != BURST_SIZE) {
     422                 :            :                                         printf("Expect to find %u keys,"
     423                 :            :                                                " but found %d\n", BURST_SIZE, ret);
     424                 :          0 :                                         return -1;
     425                 :            :                                 }
     426         [ #  # ]:          0 :                                 for (k = 0; k < BURST_SIZE; k++) {
     427         [ #  # ]:          0 :                                         if ((hit_mask & (1ULL << k))  == 0) {
     428                 :          0 :                                                 printf("Key number %u not found\n",
     429                 :          0 :                                                         j * BURST_SIZE + k);
     430                 :          0 :                                                 return -1;
     431                 :            :                                         }
     432                 :          0 :                                         expected_data[k] = (void *) ((uintptr_t) signatures[j * BURST_SIZE + k]);
     433         [ #  # ]:          0 :                                         if (ret_data[k] != expected_data[k]) {
     434                 :            :                                                 printf("Data returned for key number %u is %p,"
     435                 :            :                                                        " but should be %p\n", j * BURST_SIZE + k,
     436                 :            :                                                         ret_data[k], expected_data[k]);
     437                 :          0 :                                                 return -1;
     438                 :            :                                         }
     439                 :            :                                 }
     440         [ #  # ]:          0 :                         } else if (with_hash && with_data) {
     441                 :          0 :                                 ret = rte_hash_lookup_with_hash_bulk_data(
     442                 :          0 :                                         h[table_index],
     443                 :            :                                         (const void **)keys_burst,
     444                 :          0 :                                         &signatures[j * BURST_SIZE],
     445                 :            :                                         BURST_SIZE, &hit_mask, ret_data);
     446         [ #  # ]:          0 :                                 if (ret != BURST_SIZE) {
     447                 :            :                                         printf("Expect to find %u keys,"
     448                 :            :                                                " but found %d\n",
     449                 :            :                                                 BURST_SIZE, ret);
     450                 :          0 :                                         return -1;
     451                 :            :                                 }
     452         [ #  # ]:          0 :                                 for (k = 0; k < BURST_SIZE; k++) {
     453         [ #  # ]:          0 :                                         if ((hit_mask & (1ULL << k))  == 0) {
     454                 :          0 :                                                 printf("Key number %u"
     455                 :            :                                                         " not found\n",
     456                 :            :                                                         j * BURST_SIZE + k);
     457                 :          0 :                                                 return -1;
     458                 :            :                                         }
     459                 :            :                                         expected_data[k] =
     460                 :          0 :                                                 (void *)((uintptr_t)signatures[
     461                 :          0 :                                                 j * BURST_SIZE + k]);
     462         [ #  # ]:          0 :                                         if (ret_data[k] != expected_data[k]) {
     463                 :            :                                                 printf("Data returned for key"
     464                 :            :                                                         " number %u is %p,"
     465                 :            :                                                         " but should be %p\n",
     466                 :            :                                                         j * BURST_SIZE + k,
     467                 :            :                                                         ret_data[k],
     468                 :            :                                                         expected_data[k]);
     469                 :          0 :                                                 return -1;
     470                 :            :                                         }
     471                 :            :                                 }
     472         [ #  # ]:          0 :                         } else if (with_hash && !with_data) {
     473                 :          0 :                                 ret = rte_hash_lookup_with_hash_bulk(
     474                 :          0 :                                         h[table_index],
     475                 :            :                                         (const void **)keys_burst,
     476                 :          0 :                                         &signatures[j * BURST_SIZE],
     477                 :            :                                         BURST_SIZE, positions_burst);
     478         [ #  # ]:          0 :                                 if (ret != 0) {
     479                 :            :                                         printf("rte_hash_lookup_with_hash_bulk failed with %d\n",
     480                 :            :                                                 ret);
     481                 :          0 :                                         return -1;
     482                 :            :                                 }
     483         [ #  # ]:          0 :                                 for (k = 0; k < BURST_SIZE; k++) {
     484                 :          0 :                                         if (positions_burst[k] !=
     485                 :          0 :                                                         positions[j *
     486         [ #  # ]:          0 :                                                         BURST_SIZE + k]) {
     487                 :            :                                                 printf("Key looked up in %d, should be in %d\n",
     488                 :            :                                                         positions_burst[k],
     489                 :            :                                                         positions[j *
     490                 :            :                                                         BURST_SIZE + k]);
     491                 :          0 :                                                 return -1;
     492                 :            :                                         }
     493                 :            :                                 }
     494                 :            :                         } else {
     495                 :          0 :                                 ret = rte_hash_lookup_bulk(h[table_index],
     496                 :            :                                                 (const void **) keys_burst,
     497                 :            :                                                 BURST_SIZE,
     498                 :            :                                                 positions_burst);
     499         [ #  # ]:          0 :                                 if (ret != 0) {
     500                 :            :                                         printf("rte_hash_lookup_bulk failed with %d\n", ret);
     501                 :          0 :                                         return -1;
     502                 :            :                                 }
     503         [ #  # ]:          0 :                                 for (k = 0; k < BURST_SIZE; k++) {
     504         [ #  # ]:          0 :                                         if (positions_burst[k] != positions[j * BURST_SIZE + k]) {
     505                 :            :                                                 printf("Key looked up in %d, should be in %d\n",
     506                 :            :                                                         positions_burst[k],
     507                 :            :                                                         positions[j * BURST_SIZE + k]);
     508                 :          0 :                                                 return -1;
     509                 :            :                                         }
     510                 :            :                                 }
     511                 :            :                         }
     512                 :            :                 }
     513                 :            :         }
     514                 :            : 
     515                 :            :         const uint64_t end_tsc = rte_rdtsc();
     516                 :          0 :         const uint64_t time_taken = end_tsc - start_tsc;
     517                 :            : 
     518                 :          0 :         cycles[table_index][OP_LOOKUP_MULTI][with_hash][with_data] =
     519                 :          0 :                 time_taken/num_lookups;
     520                 :            : 
     521                 :          0 :         return 0;
     522                 :            : }
     523                 :            : 
     524                 :            : static int
     525                 :          0 : timed_deletes(unsigned int with_hash, unsigned int with_data,
     526                 :            :                                 unsigned int table_index, unsigned int ext)
     527                 :            : {
     528                 :            :         unsigned i;
     529                 :            :         const uint64_t start_tsc = rte_rdtsc();
     530                 :            :         int32_t ret;
     531                 :            :         unsigned int keys_to_add;
     532         [ #  # ]:          0 :         if (!ext)
     533                 :            :                 keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
     534                 :            :         else
     535                 :            :                 keys_to_add = KEYS_TO_ADD;
     536                 :            : 
     537         [ #  # ]:          0 :         for (i = 0; i < keys_to_add; i++) {
     538                 :            :                 /* There are no delete functions with data, so just call two functions */
     539         [ #  # ]:          0 :                 if (with_hash)
     540                 :          0 :                         ret = rte_hash_del_key_with_hash(h[table_index],
     541                 :          0 :                                                         (const void *) keys[i],
     542                 :            :                                                         signatures[i]);
     543                 :            :                 else
     544                 :          0 :                         ret = rte_hash_del_key(h[table_index],
     545                 :          0 :                                                         (const void *) keys[i]);
     546         [ #  # ]:          0 :                 if (ret >= 0)
     547                 :          0 :                         positions[i] = ret;
     548                 :            :                 else {
     549                 :            :                         printf("Failed to delete key number %u\n", i);
     550                 :          0 :                         return -1;
     551                 :            :                 }
     552                 :            :         }
     553                 :            : 
     554                 :            :         const uint64_t end_tsc = rte_rdtsc();
     555                 :          0 :         const uint64_t time_taken = end_tsc - start_tsc;
     556                 :            : 
     557                 :          0 :         cycles[table_index][OP_DELETE][with_hash][with_data] = time_taken/keys_to_add;
     558                 :            : 
     559                 :          0 :         return 0;
     560                 :            : }
     561                 :            : 
     562                 :            : static void
     563                 :            : free_table(unsigned table_index)
     564                 :            : {
     565                 :          0 :         rte_hash_free(h[table_index]);
     566                 :            : }
     567                 :            : 
     568                 :            : static void
     569                 :            : reset_table(unsigned table_index)
     570                 :            : {
     571                 :          0 :         rte_hash_reset(h[table_index]);
     572                 :            : }
     573                 :            : 
     574                 :            : static int
     575                 :          0 : run_all_tbl_perf_tests(unsigned int with_pushes, unsigned int with_locks,
     576                 :            :                                                 unsigned int ext)
     577                 :            : {
     578                 :            :         unsigned i, j, with_data, with_hash;
     579                 :            : 
     580                 :            :         printf("Measuring performance, please wait");
     581                 :          0 :         fflush(stdout);
     582                 :            : 
     583         [ #  # ]:          0 :         for (with_data = 0; with_data <= 1; with_data++) {
     584         [ #  # ]:          0 :                 for (i = 0; i < NUM_KEYSIZES; i++) {
     585         [ #  # ]:          0 :                         if (create_table(with_data, i, with_locks, ext) < 0)
     586                 :            :                                 return -1;
     587                 :            : 
     588         [ #  # ]:          0 :                         if (get_input_keys(with_pushes, i, ext) < 0)
     589                 :            :                                 return -1;
     590         [ #  # ]:          0 :                         for (with_hash = 0; with_hash <= 1; with_hash++) {
     591         [ #  # ]:          0 :                                 if (timed_adds(with_hash, with_data, i, ext) < 0)
     592                 :            :                                         return -1;
     593                 :            : 
     594         [ #  # ]:          0 :                                 for (j = 0; j < NUM_SHUFFLES; j++)
     595                 :          0 :                                         shuffle_input_keys(i, ext);
     596                 :            : 
     597         [ #  # ]:          0 :                                 if (timed_lookups(with_hash, with_data, i, ext) < 0)
     598                 :            :                                         return -1;
     599                 :            : 
     600         [ #  # ]:          0 :                                 if (timed_lookups_multi(with_hash, with_data,
     601                 :            :                                                 i, ext) < 0)
     602                 :            :                                         return -1;
     603                 :            : 
     604         [ #  # ]:          0 :                                 if (timed_deletes(with_hash, with_data, i, ext) < 0)
     605                 :            :                                         return -1;
     606                 :            : 
     607                 :            :                                 /* Print a dot to show progress on operations */
     608                 :            :                                 printf(".");
     609                 :          0 :                                 fflush(stdout);
     610                 :            : 
     611                 :            :                                 reset_table(i);
     612                 :            :                         }
     613                 :            :                         free_table(i);
     614                 :            :                 }
     615                 :            :         }
     616                 :            : 
     617                 :            :         printf("\nResults (in CPU cycles/operation)\n");
     618                 :            :         printf("-----------------------------------\n");
     619         [ #  # ]:          0 :         for (with_data = 0; with_data <= 1; with_data++) {
     620         [ #  # ]:          0 :                 if (with_data)
     621                 :            :                         printf("\n Operations with 8-byte data\n");
     622                 :            :                 else
     623                 :            :                         printf("\n Operations without data\n");
     624         [ #  # ]:          0 :                 for (with_hash = 0; with_hash <= 1; with_hash++) {
     625         [ #  # ]:          0 :                         if (with_hash)
     626                 :            :                                 printf("\nWith pre-computed hash values\n");
     627                 :            :                         else
     628                 :            :                                 printf("\nWithout pre-computed hash values\n");
     629                 :            : 
     630                 :            :                         printf("\n%-18s%-18s%-18s%-18s%-18s\n",
     631                 :            :                         "Keysize", "Add", "Lookup", "Lookup_bulk", "Delete");
     632         [ #  # ]:          0 :                         for (i = 0; i < NUM_KEYSIZES; i++) {
     633                 :          0 :                                 printf("%-18d", hashtest_key_lens[i]);
     634         [ #  # ]:          0 :                                 for (j = 0; j < NUM_OPERATIONS; j++)
     635                 :          0 :                                         printf("%-18"PRIu64, cycles[i][j][with_hash][with_data]);
     636                 :            :                                 printf("\n");
     637                 :            :                         }
     638                 :            :                 }
     639                 :            :         }
     640                 :            :         return 0;
     641                 :            : }
     642                 :            : 
     643                 :            : /* Control operation of performance testing of fbk hash. */
     644                 :            : #define LOAD_FACTOR 0.667       /* How full to make the hash table. */
     645                 :            : #define TEST_SIZE 1000000       /* How many operations to time. */
     646                 :            : #define TEST_ITERATIONS 30      /* How many measurements to take. */
     647                 :            : #define ENTRIES (1 << 15) /* How many entries. */
     648                 :            : 
     649                 :            : static int
     650                 :          0 : fbk_hash_perf_test(void)
     651                 :            : {
     652                 :          0 :         struct rte_fbk_hash_params params = {
     653                 :            :                 .name = "fbk_hash_test",
     654                 :            :                 .entries = ENTRIES,
     655                 :            :                 .entries_per_bucket = 4,
     656                 :          0 :                 .socket_id = rte_socket_id(),
     657                 :            :         };
     658                 :            :         struct rte_fbk_hash_table *handle = NULL;
     659                 :            :         uint32_t *keys = NULL;
     660                 :            :         unsigned indexes[TEST_SIZE];
     661                 :            :         uint64_t lookup_time = 0;
     662                 :            :         unsigned added = 0;
     663                 :            :         unsigned value = 0;
     664                 :            :         uint32_t key;
     665                 :            :         uint16_t val;
     666                 :            :         unsigned i, j;
     667                 :            : 
     668                 :          0 :         handle = rte_fbk_hash_create(&params);
     669         [ #  # ]:          0 :         if (handle == NULL) {
     670                 :            :                 printf("Error creating table\n");
     671                 :          0 :                 return -1;
     672                 :            :         }
     673                 :            : 
     674                 :          0 :         keys = rte_zmalloc(NULL, ENTRIES * sizeof(*keys), 0);
     675         [ #  # ]:          0 :         if (keys == NULL) {
     676                 :            :                 printf("fbk hash: memory allocation for key store failed\n");
     677                 :          0 :                 return -1;
     678                 :            :         }
     679                 :            : 
     680                 :            :         /* Generate random keys and values. */
     681         [ #  # ]:          0 :         for (i = 0; i < ENTRIES; i++) {
     682                 :          0 :                 key = (uint32_t)rte_rand();
     683                 :          0 :                 key = ((uint64_t)key << 32) | (uint64_t)rte_rand();
     684                 :          0 :                 val = (uint16_t)rte_rand();
     685                 :            : 
     686         [ #  # ]:          0 :                 if (rte_fbk_hash_add_key(handle, key, val) == 0) {
     687                 :          0 :                         keys[added] = key;
     688                 :          0 :                         added++;
     689                 :            :                 }
     690         [ #  # ]:          0 :                 if (added > (LOAD_FACTOR * ENTRIES))
     691                 :            :                         break;
     692                 :            :         }
     693                 :            : 
     694         [ #  # ]:          0 :         for (i = 0; i < TEST_ITERATIONS; i++) {
     695                 :            :                 uint64_t begin;
     696                 :            :                 uint64_t end;
     697                 :            : 
     698                 :            :                 /* Generate random indexes into keys[] array. */
     699         [ #  # ]:          0 :                 for (j = 0; j < TEST_SIZE; j++)
     700                 :          0 :                         indexes[j] = rte_rand() % added;
     701                 :            : 
     702                 :            :                 begin = rte_rdtsc();
     703                 :            :                 /* Do lookups */
     704         [ #  # ]:          0 :                 for (j = 0; j < TEST_SIZE; j++)
     705                 :          0 :                         value += rte_fbk_hash_lookup(handle, keys[indexes[j]]);
     706                 :            : 
     707                 :            :                 end = rte_rdtsc();
     708                 :          0 :                 lookup_time += (double)(end - begin);
     709                 :            :         }
     710                 :            : 
     711                 :            :         printf("\n\n *** FBK Hash function performance test results ***\n");
     712                 :            :         /*
     713                 :            :          * The use of the 'value' variable ensures that the hash lookup is not
     714                 :            :          * being optimised out by the compiler.
     715                 :            :          */
     716         [ #  # ]:          0 :         if (value != 0)
     717                 :          0 :                 printf("Number of ticks per lookup = %g\n",
     718                 :          0 :                         (double)lookup_time /
     719                 :            :                         ((double)TEST_ITERATIONS * (double)TEST_SIZE));
     720                 :            : 
     721                 :          0 :         rte_fbk_hash_free(handle);
     722                 :            : 
     723                 :          0 :         return 0;
     724                 :            : }
     725                 :            : 
     726                 :            : static int
     727                 :          0 : test_hash_perf(void)
     728                 :            : {
     729                 :            :         unsigned int with_pushes, with_locks;
     730                 :            : 
     731                 :            :         if (RTE_EXEC_ENV_IS_WINDOWS)
     732                 :            :                 return TEST_SKIPPED;
     733                 :            : 
     734         [ #  # ]:          0 :         for (with_locks = 0; with_locks <= 1; with_locks++) {
     735         [ #  # ]:          0 :                 if (with_locks)
     736                 :            :                         printf("\nWith locks in the code\n");
     737                 :            :                 else
     738                 :            :                         printf("\nWithout locks in the code\n");
     739         [ #  # ]:          0 :                 for (with_pushes = 0; with_pushes <= 1; with_pushes++) {
     740         [ #  # ]:          0 :                         if (with_pushes == 0)
     741                 :            :                                 printf("\nALL ELEMENTS IN PRIMARY LOCATION\n");
     742                 :            :                         else
     743                 :            :                                 printf("\nELEMENTS IN PRIMARY OR SECONDARY LOCATION\n");
     744         [ #  # ]:          0 :                         if (run_all_tbl_perf_tests(with_pushes, with_locks, 0) < 0)
     745                 :            :                                 return -1;
     746                 :            :                 }
     747                 :            :         }
     748                 :            : 
     749                 :            :         printf("\n EXTENDABLE BUCKETS PERFORMANCE\n");
     750                 :            : 
     751         [ #  # ]:          0 :         if (run_all_tbl_perf_tests(1, 0, 1) < 0)
     752                 :            :                 return -1;
     753                 :            : 
     754         [ #  # ]:          0 :         if (fbk_hash_perf_test() < 0)
     755                 :          0 :                 return -1;
     756                 :            : 
     757                 :            :         return 0;
     758                 :            : }
     759                 :            : 
     760                 :        252 : REGISTER_PERF_TEST(hash_perf_autotest, test_hash_perf);

Generated by: LCOV version 1.14