Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2017 Intel Corporation
3 : : */
4 : :
5 : : #include "test.h"
6 : :
7 : : #include <stdio.h>
8 : : #include <inttypes.h>
9 : :
10 : : #include <rte_lcore.h>
11 : : #include <rte_cycles.h>
12 : : #include <rte_malloc.h>
13 : : #include <rte_random.h>
14 : : #include <rte_memcpy.h>
15 : : #include <rte_thash.h>
16 : : #include <math.h>
17 : :
18 : : #ifdef RTE_EXEC_ENV_WINDOWS
19 : : static int
20 : : test_member_perf(void)
21 : : {
22 : : printf("member_perf not supported on Windows, skipping test\n");
23 : : return TEST_SKIPPED;
24 : : }
25 : :
26 : : #else
27 : :
28 : : #include <rte_member.h>
29 : :
30 : : #define NUM_KEYSIZES RTE_DIM(hashtest_key_lens)
31 : : #define NUM_SHUFFLES 10
32 : : #define MAX_KEYSIZE 64
33 : : #define MAX_ENTRIES (1 << 19)
34 : : #define KEYS_TO_ADD (MAX_ENTRIES * 75 / 100) /* 75% table utilization */
35 : : #define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */
36 : : #define VBF_SET_CNT 16
37 : : #define BURST_SIZE 64
38 : : #define VBF_FALSE_RATE 0.03
39 : :
40 : : /* for the heavy hitter detection */
41 : : #define SKETCH_LARGEST_KEY_SIZE (1<<15)
42 : : #define SKETCH_PKT_SIZE 16
43 : : #define TOP_K 100
44 : : #define SKETCH_ERROR_RATE 0.05
45 : : #define SKETCH_SAMPLE_RATE 0.001
46 : : #define NUM_ADDS (KEYS_TO_ADD * 20)
47 : :
48 : : static unsigned int test_socket_id;
49 : :
50 : : enum sstype {
51 : : HT = 0,
52 : : CACHE,
53 : : VBF,
54 : : SKETCH,
55 : : SKETCH_BOUNDED,
56 : : SKETCH_BYTE,
57 : : NUM_TYPE
58 : : };
59 : :
60 : : enum operations {
61 : : ADD = 0,
62 : : LOOKUP,
63 : : LOOKUP_BULK,
64 : : LOOKUP_MULTI,
65 : : LOOKUP_MULTI_BULK,
66 : : DELETE,
67 : : LOOKUP_MISS,
68 : : NUM_OPERATIONS
69 : : };
70 : :
71 : : struct member_perf_params {
72 : : struct rte_member_setsum *setsum[NUM_TYPE];
73 : : uint32_t key_size;
74 : : unsigned int cycle;
75 : : };
76 : :
77 : : static uint32_t hashtest_key_lens[] = {
78 : : /* standard key sizes */
79 : : 4, 8, 16, 32, 48, 64,
80 : : /* IPv4 SRC + DST + protocol, unpadded */
81 : : 9,
82 : : /* IPv4 5-tuple, unpadded */
83 : : 13,
84 : : /* IPv6 5-tuple, unpadded */
85 : : 37,
86 : : /* IPv6 5-tuple, padded to 8-byte boundary */
87 : : 40
88 : : };
89 : :
90 : : /* Array to store number of cycles per operation */
91 : : static uint64_t cycles[NUM_TYPE][NUM_KEYSIZES][NUM_OPERATIONS];
92 : : static uint64_t false_data[NUM_TYPE][NUM_KEYSIZES];
93 : : static uint64_t false_data_bulk[NUM_TYPE][NUM_KEYSIZES];
94 : : static uint64_t false_data_multi[NUM_TYPE][NUM_KEYSIZES];
95 : : static uint64_t false_data_multi_bulk[NUM_TYPE][NUM_KEYSIZES];
96 : :
97 : : static uint64_t false_hit[NUM_TYPE][NUM_KEYSIZES];
98 : :
99 : : static member_set_t data[NUM_TYPE][/* Array to store the data */KEYS_TO_ADD];
100 : :
101 : : /* Array to store all input keys */
102 : : static uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE];
103 : : static uint8_t hh_keys[KEYS_TO_ADD][MAX_KEYSIZE];
104 : :
105 : : /* Shuffle the keys that have been added, so lookups will be totally random */
106 : : static void
107 : 0 : shuffle_input_keys(struct member_perf_params *params)
108 : : {
109 : : member_set_t temp_data;
110 : : unsigned int i, j;
111 : : uint32_t swap_idx;
112 : : uint8_t temp_key[MAX_KEYSIZE];
113 : :
114 [ # # ]: 0 : for (i = KEYS_TO_ADD - 1; i > 0; i--) {
115 : 0 : swap_idx = rte_rand() % i;
116 : 0 : memcpy(temp_key, keys[i], hashtest_key_lens[params->cycle]);
117 : 0 : memcpy(keys[i], keys[swap_idx],
118 : : hashtest_key_lens[params->cycle]);
119 : 0 : memcpy(keys[swap_idx], temp_key,
120 : 0 : hashtest_key_lens[params->cycle]);
121 [ # # ]: 0 : for (j = 0; j < NUM_TYPE; j++) {
122 : 0 : temp_data = data[j][i];
123 : 0 : data[j][i] = data[j][swap_idx];
124 : 0 : data[j][swap_idx] = temp_data;
125 : : }
126 : : }
127 : 0 : }
128 : :
129 : 0 : static int key_compare(const void *key1, const void *key2)
130 : : {
131 : 0 : return memcmp(key1, key2, MAX_KEYSIZE);
132 : : }
133 : :
134 : : struct rte_member_parameters member_params = {
135 : : .num_keys = MAX_ENTRIES, /* Total hash table entries. */
136 : : .key_len = 4, /* Length of hash key. */
137 : :
138 : : /* num_set and false_positive_rate only relevant to vBF */
139 : : .num_set = VBF_SET_CNT,
140 : : .false_positive_rate = 0.03,
141 : : .prim_hash_seed = 0,
142 : : .sec_hash_seed = 1,
143 : : .socket_id = 0, /* NUMA Socket ID for memory. */
144 : : };
145 : :
146 : : static int
147 : 0 : setup_keys_and_data(struct member_perf_params *params, unsigned int cycle,
148 : : int miss)
149 : : {
150 : : unsigned int i, j;
151 : : int num_duplicates;
152 : : int distinct_key = 0;
153 : : int count_down = SKETCH_LARGEST_KEY_SIZE;
154 : : uint32_t swap_idx;
155 : : uint8_t temp_key[MAX_KEYSIZE];
156 : :
157 : 0 : params->key_size = hashtest_key_lens[cycle];
158 : 0 : params->cycle = cycle;
159 : :
160 : : /* Reset all arrays */
161 [ # # ]: 0 : for (i = 0; i < params->key_size; i++)
162 : 0 : keys[0][i] = 0;
163 : :
164 : : /* Generate a list of keys, some of which may be duplicates */
165 [ # # ]: 0 : for (i = 0; i < KEYS_TO_ADD; i++) {
166 [ # # ]: 0 : for (j = 0; j < params->key_size; j++)
167 : 0 : keys[i][j] = rte_rand() & 0xFF;
168 : :
169 : 0 : data[HT][i] = data[CACHE][i] = (rte_rand() & 0x7FFE) + 1;
170 : 0 : data[VBF][i] = rte_rand() % VBF_SET_CNT + 1;
171 : : }
172 : :
173 : : /* Remove duplicates from the keys array */
174 : : do {
175 : : num_duplicates = 0;
176 : :
177 : : /* Sort the list of keys to make it easier to find duplicates */
178 : 0 : qsort(keys, KEYS_TO_ADD, MAX_KEYSIZE, key_compare);
179 : :
180 : : /* Sift through the list of keys and look for duplicates */
181 [ # # ]: 0 : for (i = 0; i < KEYS_TO_ADD - 1; i++) {
182 : 0 : if (memcmp(keys[i], keys[i + 1],
183 [ # # ]: 0 : params->key_size) == 0) {
184 : : /* This key already exists, try again */
185 : 0 : num_duplicates++;
186 [ # # ]: 0 : for (j = 0; j < params->key_size; j++)
187 : 0 : keys[i][j] = rte_rand() & 0xFF;
188 : : }
189 : : }
190 [ # # ]: 0 : } while (num_duplicates != 0);
191 : :
192 : : /* Shuffle the random values again */
193 : 0 : shuffle_input_keys(params);
194 : :
195 [ # # ]: 0 : for (i = 0; i < KEYS_TO_ADD; i++) {
196 [ # # ]: 0 : if (count_down == 0) {
197 : 0 : distinct_key++;
198 : 0 : count_down = ceil((double)SKETCH_LARGEST_KEY_SIZE /
199 : 0 : (distinct_key + 1));
200 : : }
201 : 0 : memcpy(hh_keys[i], keys[distinct_key], params->key_size);
202 : 0 : count_down--;
203 : : }
204 : :
205 [ # # ]: 0 : for (i = KEYS_TO_ADD - 1; i > 0; i--) {
206 : 0 : swap_idx = rte_rand() % i;
207 : 0 : memcpy(temp_key, hh_keys[i], params->key_size);
208 : 0 : memcpy(hh_keys[i], hh_keys[swap_idx], params->key_size);
209 : 0 : memcpy(hh_keys[swap_idx], temp_key, params->key_size);
210 : : }
211 : :
212 : : /* For testing miss lookup, we insert half and lookup the other half */
213 : : unsigned int entry_cnt, bf_key_cnt;
214 [ # # ]: 0 : if (!miss) {
215 : : entry_cnt = MAX_ENTRIES;
216 : : bf_key_cnt = KEYS_TO_ADD;
217 : : } else {
218 : : entry_cnt = MAX_ENTRIES / 2;
219 : : bf_key_cnt = KEYS_TO_ADD / 2;
220 : : }
221 : 0 : member_params.false_positive_rate = VBF_FALSE_RATE;
222 : 0 : member_params.key_len = params->key_size;
223 : 0 : member_params.socket_id = test_socket_id;
224 : 0 : member_params.num_keys = entry_cnt;
225 : 0 : member_params.name = "test_member_ht";
226 : 0 : member_params.is_cache = 0;
227 : 0 : member_params.type = RTE_MEMBER_TYPE_HT;
228 : 0 : params->setsum[HT] = rte_member_create(&member_params);
229 [ # # ]: 0 : if (params->setsum[HT] == NULL)
230 : 0 : fprintf(stderr, "ht create fail\n");
231 : :
232 : 0 : member_params.name = "test_member_cache";
233 : 0 : member_params.is_cache = 1;
234 : 0 : params->setsum[CACHE] = rte_member_create(&member_params);
235 [ # # ]: 0 : if (params->setsum[CACHE] == NULL)
236 : 0 : fprintf(stderr, "CACHE create fail\n");
237 : :
238 : 0 : member_params.name = "test_member_vbf";
239 : 0 : member_params.type = RTE_MEMBER_TYPE_VBF;
240 : 0 : member_params.num_keys = bf_key_cnt;
241 : 0 : params->setsum[VBF] = rte_member_create(&member_params);
242 [ # # ]: 0 : if (params->setsum[VBF] == NULL)
243 : 0 : fprintf(stderr, "VBF create fail\n");
244 : :
245 : 0 : member_params.name = "test_member_sketch";
246 : 0 : member_params.key_len = params->key_size;
247 : 0 : member_params.type = RTE_MEMBER_TYPE_SKETCH;
248 : 0 : member_params.error_rate = SKETCH_ERROR_RATE;
249 : 0 : member_params.sample_rate = SKETCH_SAMPLE_RATE;
250 : 0 : member_params.extra_flag = 0;
251 : 0 : member_params.top_k = TOP_K;
252 : 0 : member_params.prim_hash_seed = rte_rdtsc();
253 : 0 : params->setsum[SKETCH] = rte_member_create(&member_params);
254 [ # # ]: 0 : if (params->setsum[SKETCH] == NULL)
255 : 0 : fprintf(stderr, "sketch create fail\n");
256 : :
257 : 0 : member_params.name = "test_member_sketch_bounded";
258 : 0 : member_params.key_len = params->key_size;
259 : 0 : member_params.type = RTE_MEMBER_TYPE_SKETCH;
260 : 0 : member_params.error_rate = SKETCH_ERROR_RATE;
261 : 0 : member_params.sample_rate = SKETCH_SAMPLE_RATE;
262 : 0 : member_params.extra_flag |= RTE_MEMBER_SKETCH_ALWAYS_BOUNDED;
263 : 0 : member_params.top_k = TOP_K;
264 : 0 : member_params.prim_hash_seed = rte_rdtsc();
265 : 0 : params->setsum[SKETCH_BOUNDED] = rte_member_create(&member_params);
266 [ # # ]: 0 : if (params->setsum[SKETCH_BOUNDED] == NULL)
267 : 0 : fprintf(stderr, "sketch create fail\n");
268 : :
269 : 0 : member_params.name = "test_member_sketch_byte";
270 : 0 : member_params.key_len = params->key_size;
271 : 0 : member_params.type = RTE_MEMBER_TYPE_SKETCH;
272 : 0 : member_params.error_rate = SKETCH_ERROR_RATE;
273 : 0 : member_params.sample_rate = SKETCH_SAMPLE_RATE;
274 : 0 : member_params.extra_flag |= RTE_MEMBER_SKETCH_COUNT_BYTE;
275 : 0 : member_params.top_k = TOP_K;
276 : 0 : member_params.prim_hash_seed = rte_rdtsc();
277 : 0 : params->setsum[SKETCH_BYTE] = rte_member_create(&member_params);
278 [ # # ]: 0 : if (params->setsum[SKETCH_BYTE] == NULL)
279 : 0 : fprintf(stderr, "sketch create fail\n");
280 : :
281 : :
282 [ # # ]: 0 : for (i = 0; i < NUM_TYPE; i++) {
283 [ # # ]: 0 : if (params->setsum[i] == NULL)
284 : : return -1;
285 : : }
286 : :
287 : : return 0;
288 : : }
289 : :
290 : : static int
291 : 0 : timed_adds(struct member_perf_params *params, int type)
292 : : {
293 : : const uint64_t start_tsc = rte_rdtsc();
294 : : unsigned int i, a;
295 : : int32_t ret;
296 : :
297 [ # # ]: 0 : for (i = 0; i < KEYS_TO_ADD; i++) {
298 : 0 : ret = rte_member_add(params->setsum[type], &keys[i],
299 : 0 : data[type][i]);
300 [ # # ]: 0 : if (ret < 0) {
301 : : printf("Error %d in rte_member_add - key=0x", ret);
302 [ # # ]: 0 : for (a = 0; a < params->key_size; a++)
303 : 0 : printf("%02x", keys[i][a]);
304 : 0 : printf(" value=%d, type: %d\n", data[type][i], type);
305 : :
306 : 0 : return -1;
307 : : }
308 : : }
309 : :
310 : : const uint64_t end_tsc = rte_rdtsc();
311 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
312 : :
313 : 0 : cycles[type][params->cycle][ADD] = time_taken / KEYS_TO_ADD;
314 : 0 : return 0;
315 : : }
316 : :
317 : : static int
318 : 0 : timed_adds_sketch(struct member_perf_params *params, int type)
319 : : {
320 : : const uint64_t start_tsc = rte_rdtsc();
321 : : unsigned int i, j, a;
322 : : int32_t ret;
323 : :
324 [ # # ]: 0 : for (i = 0; i < NUM_ADDS / KEYS_TO_ADD; i++) {
325 [ # # ]: 0 : for (j = 0; j < KEYS_TO_ADD; j++) {
326 [ # # ]: 0 : if (type == SKETCH_BYTE)
327 : 0 : ret = rte_member_add_byte_count(params->setsum[type],
328 : 0 : &hh_keys[j], SKETCH_PKT_SIZE);
329 : : else
330 : 0 : ret = rte_member_add(params->setsum[type], &hh_keys[j], 1);
331 [ # # ]: 0 : if (ret < 0) {
332 : : printf("Error %d in rte_member_add - key=0x", ret);
333 [ # # ]: 0 : for (a = 0; a < params->key_size; a++)
334 : 0 : printf("%02x", hh_keys[j][a]);
335 : : printf("type: %d\n", type);
336 : :
337 : 0 : return -1;
338 : : }
339 : : }
340 : : }
341 : :
342 : : const uint64_t end_tsc = rte_rdtsc();
343 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
344 : :
345 : 0 : cycles[type][params->cycle][ADD] = time_taken / NUM_ADDS;
346 : :
347 : 0 : return 0;
348 : : }
349 : :
350 : : static int
351 : 0 : timed_lookups(struct member_perf_params *params, int type)
352 : : {
353 : : unsigned int i, j;
354 : :
355 : 0 : false_data[type][params->cycle] = 0;
356 : :
357 : : const uint64_t start_tsc = rte_rdtsc();
358 : : member_set_t result;
359 : : int ret;
360 : :
361 [ # # ]: 0 : for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
362 [ # # ]: 0 : for (j = 0; j < KEYS_TO_ADD; j++) {
363 : 0 : ret = rte_member_lookup(params->setsum[type], &keys[j],
364 : : &result);
365 [ # # ]: 0 : if (ret < 0) {
366 : : printf("lookup wrong internally");
367 : 0 : return -1;
368 : : }
369 [ # # # # ]: 0 : if (type == HT && result == RTE_MEMBER_NO_MATCH) {
370 : : printf("HT mode shouldn't have false negative");
371 : 0 : return -1;
372 : : }
373 [ # # ]: 0 : if (result != data[type][j])
374 : 0 : false_data[type][params->cycle]++;
375 : : }
376 : : }
377 : :
378 : : const uint64_t end_tsc = rte_rdtsc();
379 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
380 : :
381 : 0 : cycles[type][params->cycle][LOOKUP] = time_taken / NUM_LOOKUPS;
382 : :
383 : 0 : return 0;
384 : : }
385 : :
386 : : static int
387 : 0 : timed_lookups_sketch(struct member_perf_params *params, int type)
388 : : {
389 : : unsigned int i, j;
390 : :
391 : 0 : false_data[type][params->cycle] = 0;
392 : :
393 : : const uint64_t start_tsc = rte_rdtsc();
394 : : member_set_t result;
395 : : int ret;
396 : :
397 [ # # ]: 0 : for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
398 [ # # ]: 0 : for (j = 0; j < KEYS_TO_ADD; j++) {
399 : 0 : ret = rte_member_lookup(params->setsum[type], &hh_keys[j],
400 : : &result);
401 [ # # ]: 0 : if (ret < 0) {
402 : : printf("lookup wrong internally");
403 : 0 : return -1;
404 : : }
405 : : }
406 : : }
407 : :
408 : : const uint64_t end_tsc = rte_rdtsc();
409 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
410 : :
411 : 0 : cycles[type][params->cycle][LOOKUP] = time_taken / NUM_LOOKUPS;
412 : :
413 : 0 : return 0;
414 : : }
415 : :
416 : : static int
417 : 0 : timed_lookups_bulk(struct member_perf_params *params, int type)
418 : : {
419 : : unsigned int i, j, k;
420 : 0 : member_set_t result[BURST_SIZE] = {0};
421 : : const void *keys_burst[BURST_SIZE];
422 : : int ret;
423 : :
424 : 0 : false_data_bulk[type][params->cycle] = 0;
425 : :
426 : : const uint64_t start_tsc = rte_rdtsc();
427 : :
428 [ # # ]: 0 : for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
429 [ # # ]: 0 : for (j = 0; j < KEYS_TO_ADD / BURST_SIZE; j++) {
430 [ # # ]: 0 : for (k = 0; k < BURST_SIZE; k++)
431 : 0 : keys_burst[k] = keys[j * BURST_SIZE + k];
432 : :
433 : 0 : ret = rte_member_lookup_bulk(params->setsum[type],
434 : : keys_burst,
435 : : BURST_SIZE,
436 : : result);
437 [ # # ]: 0 : if (ret <= 0) {
438 : : printf("lookup bulk has wrong return value\n");
439 : 0 : return -1;
440 : : }
441 [ # # ]: 0 : for (k = 0; k < BURST_SIZE; k++) {
442 : 0 : uint32_t data_idx = j * BURST_SIZE + k;
443 [ # # # # ]: 0 : if (type == HT && result[k] ==
444 : : RTE_MEMBER_NO_MATCH) {
445 : : printf("HT mode shouldn't have "
446 : : "false negative");
447 : 0 : return -1;
448 : : }
449 [ # # ]: 0 : if (result[k] != data[type][data_idx])
450 : 0 : false_data_bulk[type][params->cycle]++;
451 : : }
452 : : }
453 : : }
454 : :
455 : : const uint64_t end_tsc = rte_rdtsc();
456 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
457 : :
458 : 0 : cycles[type][params->cycle][LOOKUP_BULK] = time_taken / NUM_LOOKUPS;
459 : :
460 : 0 : return 0;
461 : : }
462 : :
463 : : static int
464 : 0 : timed_lookups_multimatch(struct member_perf_params *params, int type)
465 : : {
466 : : unsigned int i, j;
467 : 0 : member_set_t result[RTE_MEMBER_BUCKET_ENTRIES] = {0};
468 : : int ret;
469 : 0 : false_data_multi[type][params->cycle] = 0;
470 : :
471 : : const uint64_t start_tsc = rte_rdtsc();
472 : :
473 [ # # ]: 0 : for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
474 [ # # ]: 0 : for (j = 0; j < KEYS_TO_ADD; j++) {
475 : 0 : ret = rte_member_lookup_multi(params->setsum[type],
476 : 0 : &keys[j], RTE_MEMBER_BUCKET_ENTRIES, result);
477 [ # # ]: 0 : if (type != CACHE && ret <= 0) {
478 : : printf("lookup multi has wrong return value %d,"
479 : : "type %d\n", ret, type);
480 : : }
481 [ # # ]: 0 : if (type == HT && ret == 0) {
482 : : printf("HT mode shouldn't have false negative");
483 : 0 : return -1;
484 : : }
485 : : /*
486 : : * For performance test purpose, we do not iterate all
487 : : * results here. We assume most likely each key can only
488 : : * find one match which is result[0].
489 : : */
490 [ # # ]: 0 : if (result[0] != data[type][j])
491 : 0 : false_data_multi[type][params->cycle]++;
492 : : }
493 : : }
494 : :
495 : : const uint64_t end_tsc = rte_rdtsc();
496 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
497 : :
498 : 0 : cycles[type][params->cycle][LOOKUP_MULTI] = time_taken / NUM_LOOKUPS;
499 : :
500 : 0 : return 0;
501 : : }
502 : :
503 : : static int
504 : 0 : timed_lookups_multimatch_bulk(struct member_perf_params *params, int type)
505 : : {
506 : : unsigned int i, j, k;
507 : 0 : member_set_t result[BURST_SIZE][RTE_MEMBER_BUCKET_ENTRIES] = {{0} };
508 : : const void *keys_burst[BURST_SIZE];
509 : : uint32_t match_count[BURST_SIZE];
510 : : int ret;
511 : :
512 : 0 : false_data_multi_bulk[type][params->cycle] = 0;
513 : :
514 : : const uint64_t start_tsc = rte_rdtsc();
515 : :
516 [ # # ]: 0 : for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
517 [ # # ]: 0 : for (j = 0; j < KEYS_TO_ADD / BURST_SIZE; j++) {
518 [ # # ]: 0 : for (k = 0; k < BURST_SIZE; k++)
519 : 0 : keys_burst[k] = keys[j * BURST_SIZE + k];
520 : :
521 : 0 : ret = rte_member_lookup_multi_bulk(
522 : 0 : params->setsum[type],
523 : : keys_burst, BURST_SIZE,
524 : : RTE_MEMBER_BUCKET_ENTRIES, match_count,
525 : : (member_set_t *)result);
526 [ # # ]: 0 : if (ret < 0) {
527 : : printf("lookup multimatch bulk has wrong return"
528 : : " value\n");
529 : 0 : return -1;
530 : : }
531 [ # # ]: 0 : for (k = 0; k < BURST_SIZE; k++) {
532 [ # # # # ]: 0 : if (type != CACHE && match_count[k] == 0) {
533 : : printf("lookup multimatch bulk get "
534 : : "wrong match count\n");
535 : 0 : return -1;
536 : : }
537 [ # # # # ]: 0 : if (type == HT && match_count[k] == 0) {
538 : : printf("HT mode shouldn't have "
539 : : "false negative");
540 : 0 : return -1;
541 : : }
542 : 0 : uint32_t data_idx = j * BURST_SIZE + k;
543 [ # # ]: 0 : if (result[k][0] != data[type][data_idx])
544 : 0 : false_data_multi_bulk[type][params->cycle]++;
545 : : }
546 : : }
547 : : }
548 : :
549 : : const uint64_t end_tsc = rte_rdtsc();
550 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
551 : :
552 : 0 : cycles[type][params->cycle][LOOKUP_MULTI_BULK] = time_taken /
553 : : NUM_LOOKUPS;
554 : :
555 : 0 : return 0;
556 : : }
557 : :
558 : : static int
559 : 0 : timed_deletes(struct member_perf_params *params, int type)
560 : : {
561 : : unsigned int i;
562 : : int32_t ret;
563 : :
564 [ # # ]: 0 : if (type == VBF)
565 : : return 0;
566 : : const uint64_t start_tsc = rte_rdtsc();
567 [ # # ]: 0 : for (i = 0; i < KEYS_TO_ADD; i++) {
568 : 0 : ret = rte_member_delete(params->setsum[type], &keys[i],
569 : 0 : data[type][i]);
570 [ # # ]: 0 : if (type != CACHE && ret < 0) {
571 : : printf("delete error\n");
572 : 0 : return -1;
573 : : }
574 : : }
575 : :
576 : : const uint64_t end_tsc = rte_rdtsc();
577 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
578 : :
579 : 0 : cycles[type][params->cycle][DELETE] = time_taken / KEYS_TO_ADD;
580 : :
581 : 0 : return 0;
582 : : }
583 : :
584 : : static int
585 : 0 : timed_miss_lookup(struct member_perf_params *params, int type)
586 : : {
587 : : unsigned int i, j;
588 : : int ret;
589 : :
590 : 0 : false_hit[type][params->cycle] = 0;
591 : :
592 [ # # ]: 0 : for (i = 0; i < KEYS_TO_ADD / 2; i++) {
593 : 0 : ret = rte_member_add(params->setsum[type], &keys[i],
594 : 0 : data[type][i]);
595 [ # # ]: 0 : if (ret < 0) {
596 : : unsigned int a;
597 : : printf("Error %d in rte_member_add - key=0x", ret);
598 [ # # ]: 0 : for (a = 0; a < params->key_size; a++)
599 : 0 : printf("%02x", keys[i][a]);
600 : 0 : printf(" value=%d, type: %d\n", data[type][i], type);
601 : :
602 : 0 : return -1;
603 : : }
604 : : }
605 : :
606 : : const uint64_t start_tsc = rte_rdtsc();
607 : : member_set_t result;
608 : :
609 [ # # ]: 0 : for (i = 0; i < 2 * NUM_LOOKUPS / KEYS_TO_ADD; i++) {
610 [ # # ]: 0 : for (j = KEYS_TO_ADD / 2; j < KEYS_TO_ADD; j++) {
611 : 0 : ret = rte_member_lookup(params->setsum[type], &keys[j],
612 : : &result);
613 [ # # ]: 0 : if (ret < 0) {
614 : : printf("lookup wrong internally");
615 : 0 : return -1;
616 : : }
617 [ # # ]: 0 : if (result != RTE_MEMBER_NO_MATCH)
618 : 0 : false_hit[type][params->cycle]++;
619 : : }
620 : : }
621 : :
622 : : const uint64_t end_tsc = rte_rdtsc();
623 : 0 : const uint64_t time_taken = end_tsc - start_tsc;
624 : :
625 : 0 : cycles[type][params->cycle][LOOKUP_MISS] = time_taken / NUM_LOOKUPS;
626 : :
627 : 0 : return 0;
628 : : }
629 : :
630 : : static void
631 : 0 : perform_frees(struct member_perf_params *params)
632 : : {
633 : : int i;
634 [ # # ]: 0 : for (i = 0; i < NUM_TYPE; i++) {
635 [ # # ]: 0 : if (params->setsum[i] != NULL) {
636 : 0 : rte_member_free(params->setsum[i]);
637 : 0 : params->setsum[i] = NULL;
638 : : }
639 : : }
640 : 0 : }
641 : :
642 : : static int
643 : 0 : exit_with_fail(const char *testname, struct member_perf_params *params,
644 : : unsigned int i, unsigned int j)
645 : : {
646 : 0 : printf("<<<<<Test %s failed at keysize %d iteration %d type %d>>>>>\n",
647 : 0 : testname, hashtest_key_lens[params->cycle], i, j);
648 : 0 : perform_frees(params);
649 : 0 : return -1;
650 : : }
651 : :
652 : : static int
653 : 0 : run_all_tbl_perf_tests(void)
654 : : {
655 : : unsigned int i, j, k;
656 : : struct member_perf_params params;
657 : :
658 : : printf("Measuring performance, please wait\n");
659 : 0 : fflush(stdout);
660 : :
661 : 0 : test_socket_id = rte_socket_id();
662 : :
663 [ # # ]: 0 : for (i = 0; i < NUM_KEYSIZES; i++) {
664 [ # # ]: 0 : if (setup_keys_and_data(¶ms, i, 0) < 0) {
665 : : printf("Could not create keys/data/table\n");
666 : 0 : return -1;
667 : : }
668 [ # # ]: 0 : for (j = 0; j < SKETCH; j++) {
669 : :
670 [ # # ]: 0 : if (timed_adds(¶ms, j) < 0)
671 : 0 : return exit_with_fail("timed_adds", ¶ms,
672 : : i, j);
673 : :
674 [ # # ]: 0 : for (k = 0; k < NUM_SHUFFLES; k++)
675 : 0 : shuffle_input_keys(¶ms);
676 : :
677 [ # # ]: 0 : if (timed_lookups(¶ms, j) < 0)
678 : 0 : return exit_with_fail("timed_lookups", ¶ms,
679 : : i, j);
680 : :
681 [ # # ]: 0 : if (timed_lookups_bulk(¶ms, j) < 0)
682 : 0 : return exit_with_fail("timed_lookups_bulk",
683 : : ¶ms, i, j);
684 : :
685 [ # # ]: 0 : if (timed_lookups_multimatch(¶ms, j) < 0)
686 : 0 : return exit_with_fail("timed_lookups_multi",
687 : : ¶ms, i, j);
688 : :
689 [ # # ]: 0 : if (timed_lookups_multimatch_bulk(¶ms, j) < 0)
690 : 0 : return exit_with_fail("timed_lookups_multi_bulk",
691 : : ¶ms, i, j);
692 : :
693 [ # # ]: 0 : if (timed_deletes(¶ms, j) < 0)
694 : 0 : return exit_with_fail("timed_deletes", ¶ms,
695 : : i, j);
696 : :
697 : : /* Print a dot to show progress on operations */
698 : : }
699 : :
700 [ # # ]: 0 : for (j = SKETCH; j < NUM_TYPE; j++) {
701 [ # # ]: 0 : if (timed_adds_sketch(¶ms, j) < 0)
702 : 0 : return exit_with_fail
703 : : ("timed_adds_sketch", ¶ms, i, j);
704 : :
705 [ # # ]: 0 : if (timed_lookups_sketch(¶ms, j) < 0)
706 : 0 : return exit_with_fail
707 : : ("timed_lookups_sketch", ¶ms, i, j);
708 : : }
709 : :
710 : : printf(".");
711 : 0 : fflush(stdout);
712 : :
713 : 0 : perform_frees(¶ms);
714 : : }
715 : :
716 : : /* Test false positive rate using un-inserted keys */
717 [ # # ]: 0 : for (i = 0; i < NUM_KEYSIZES; i++) {
718 [ # # ]: 0 : if (setup_keys_and_data(¶ms, i, 1) < 0) {
719 : : printf("Could not create keys/data/table\n");
720 : 0 : return -1;
721 : : }
722 [ # # ]: 0 : for (j = 0; j < SKETCH; j++) {
723 [ # # ]: 0 : if (timed_miss_lookup(¶ms, j) < 0)
724 : 0 : return exit_with_fail("timed_miss_lookup",
725 : : ¶ms, i, j);
726 : : }
727 : 0 : perform_frees(¶ms);
728 : : }
729 : :
730 : : printf("\nResults (in CPU cycles/operation)\n");
731 : : printf("-----------------------------------\n");
732 : : printf("\n%-18s%-18s%-18s%-18s%-18s%-18s%-18s%-18s%-18s\n",
733 : : "Keysize", "type", "Add", "Lookup", "Lookup_bulk",
734 : : "lookup_multi", "lookup_multi_bulk", "Delete",
735 : : "miss_lookup");
736 [ # # ]: 0 : for (i = 0; i < NUM_KEYSIZES; i++) {
737 [ # # ]: 0 : for (j = 0; j < NUM_TYPE; j++) {
738 : 0 : printf("%-18d", hashtest_key_lens[i]);
739 : : printf("%-18d", j);
740 [ # # ]: 0 : for (k = 0; k < NUM_OPERATIONS; k++)
741 : 0 : printf("%-18"PRIu64, cycles[j][i][k]);
742 : : printf("\n");
743 : : }
744 : : }
745 : :
746 : : printf("\nFalse results rate (and false positive rate)\n");
747 : : printf("-----------------------------------\n");
748 : : printf("\n%-18s%-18s%-18s%-18s%-18s%-18s%-18s\n",
749 : : "Keysize", "type", "fr_single", "fr_bulk", "fr_multi",
750 : : "fr_multi_bulk", "false_positive_rate");
751 : : /* Key size not influence False rate so just print out one key size */
752 [ # # ]: 0 : for (i = 0; i < 1; i++) {
753 [ # # ]: 0 : for (j = 0; j < SKETCH; j++) {
754 : 0 : printf("%-18d", hashtest_key_lens[i]);
755 : : printf("%-18d", j);
756 : 0 : printf("%-18f", (float)false_data[j][i] / NUM_LOOKUPS);
757 : 0 : printf("%-18f", (float)false_data_bulk[j][i] /
758 : : NUM_LOOKUPS);
759 : 0 : printf("%-18f", (float)false_data_multi[j][i] /
760 : : NUM_LOOKUPS);
761 : 0 : printf("%-18f", (float)false_data_multi_bulk[j][i] /
762 : : NUM_LOOKUPS);
763 : 0 : printf("%-18f", (float)false_hit[j][i] /
764 : : NUM_LOOKUPS);
765 : : printf("\n");
766 : : }
767 : : }
768 : : return 0;
769 : : }
770 : :
771 : : static int
772 : 0 : test_member_perf(void)
773 : : {
774 : :
775 [ # # ]: 0 : if (run_all_tbl_perf_tests() < 0)
776 : 0 : return -1;
777 : :
778 : : return 0;
779 : : }
780 : :
781 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
782 : :
783 : 251 : REGISTER_PERF_TEST(member_perf_autotest, test_member_perf);
|