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