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 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 for (i = KEYS_TO_ADD - 1; i > 0; i--) { 115 swap_idx = rte_rand() % i; 116 memcpy(temp_key, keys[i], hashtest_key_lens[params->cycle]); 117 memcpy(keys[i], keys[swap_idx], 118 hashtest_key_lens[params->cycle]); 119 memcpy(keys[swap_idx], temp_key, 120 hashtest_key_lens[params->cycle]); 121 for (j = 0; j < NUM_TYPE; j++) { 122 temp_data = data[j][i]; 123 data[j][i] = data[j][swap_idx]; 124 data[j][swap_idx] = temp_data; 125 } 126 } 127 } 128 129 static int key_compare(const void *key1, const void *key2) 130 { 131 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 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 params->key_size = hashtest_key_lens[cycle]; 158 params->cycle = cycle; 159 160 /* Reset all arrays */ 161 for (i = 0; i < params->key_size; i++) 162 keys[0][i] = 0; 163 164 /* Generate a list of keys, some of which may be duplicates */ 165 for (i = 0; i < KEYS_TO_ADD; i++) { 166 for (j = 0; j < params->key_size; j++) 167 keys[i][j] = rte_rand() & 0xFF; 168 169 data[HT][i] = data[CACHE][i] = (rte_rand() & 0x7FFE) + 1; 170 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 qsort(keys, KEYS_TO_ADD, MAX_KEYSIZE, key_compare); 179 180 /* Sift through the list of keys and look for duplicates */ 181 int num_duplicates = 0; 182 for (i = 0; i < KEYS_TO_ADD - 1; i++) { 183 if (memcmp(keys[i], keys[i + 1], 184 params->key_size) == 0) { 185 /* This key already exists, try again */ 186 num_duplicates++; 187 for (j = 0; j < params->key_size; j++) 188 keys[i][j] = rte_rand() & 0xFF; 189 } 190 } 191 } while (num_duplicates != 0); 192 193 /* Shuffle the random values again */ 194 shuffle_input_keys(params); 195 196 for (i = 0; i < KEYS_TO_ADD; i++) { 197 if (count_down == 0) { 198 distinct_key++; 199 count_down = ceil((double)SKETCH_LARGEST_KEY_SIZE / 200 (distinct_key + 1)); 201 } 202 memcpy(hh_keys[i], keys[distinct_key], params->key_size); 203 count_down--; 204 } 205 206 for (i = KEYS_TO_ADD - 1; i > 0; i--) { 207 swap_idx = rte_rand() % i; 208 memcpy(temp_key, hh_keys[i], params->key_size); 209 memcpy(hh_keys[i], hh_keys[swap_idx], params->key_size); 210 memcpy(hh_keys[swap_idx], temp_key, params->key_size); 211 } 212 213 /* For testing miss lookup, we insert half and lookup the other half */ 214 unsigned int entry_cnt, bf_key_cnt; 215 if (!miss) { 216 entry_cnt = MAX_ENTRIES; 217 bf_key_cnt = KEYS_TO_ADD; 218 } else { 219 entry_cnt = MAX_ENTRIES / 2; 220 bf_key_cnt = KEYS_TO_ADD / 2; 221 } 222 member_params.false_positive_rate = VBF_FALSE_RATE; 223 member_params.key_len = params->key_size; 224 member_params.socket_id = test_socket_id; 225 member_params.num_keys = entry_cnt; 226 member_params.name = "test_member_ht"; 227 member_params.is_cache = 0; 228 member_params.type = RTE_MEMBER_TYPE_HT; 229 params->setsum[HT] = rte_member_create(&member_params); 230 if (params->setsum[HT] == NULL) 231 fprintf(stderr, "ht create fail\n"); 232 233 member_params.name = "test_member_cache"; 234 member_params.is_cache = 1; 235 params->setsum[CACHE] = rte_member_create(&member_params); 236 if (params->setsum[CACHE] == NULL) 237 fprintf(stderr, "CACHE create fail\n"); 238 239 member_params.name = "test_member_vbf"; 240 member_params.type = RTE_MEMBER_TYPE_VBF; 241 member_params.num_keys = bf_key_cnt; 242 params->setsum[VBF] = rte_member_create(&member_params); 243 if (params->setsum[VBF] == NULL) 244 fprintf(stderr, "VBF create fail\n"); 245 246 member_params.name = "test_member_sketch"; 247 member_params.key_len = params->key_size; 248 member_params.type = RTE_MEMBER_TYPE_SKETCH; 249 member_params.error_rate = SKETCH_ERROR_RATE; 250 member_params.sample_rate = SKETCH_SAMPLE_RATE; 251 member_params.extra_flag = 0; 252 member_params.top_k = TOP_K; 253 member_params.prim_hash_seed = rte_rdtsc(); 254 params->setsum[SKETCH] = rte_member_create(&member_params); 255 if (params->setsum[SKETCH] == NULL) 256 fprintf(stderr, "sketch create fail\n"); 257 258 member_params.name = "test_member_sketch_bounded"; 259 member_params.key_len = params->key_size; 260 member_params.type = RTE_MEMBER_TYPE_SKETCH; 261 member_params.error_rate = SKETCH_ERROR_RATE; 262 member_params.sample_rate = SKETCH_SAMPLE_RATE; 263 member_params.extra_flag |= RTE_MEMBER_SKETCH_ALWAYS_BOUNDED; 264 member_params.top_k = TOP_K; 265 member_params.prim_hash_seed = rte_rdtsc(); 266 params->setsum[SKETCH_BOUNDED] = rte_member_create(&member_params); 267 if (params->setsum[SKETCH_BOUNDED] == NULL) 268 fprintf(stderr, "sketch create fail\n"); 269 270 member_params.name = "test_member_sketch_byte"; 271 member_params.key_len = params->key_size; 272 member_params.type = RTE_MEMBER_TYPE_SKETCH; 273 member_params.error_rate = SKETCH_ERROR_RATE; 274 member_params.sample_rate = SKETCH_SAMPLE_RATE; 275 member_params.extra_flag |= RTE_MEMBER_SKETCH_COUNT_BYTE; 276 member_params.top_k = TOP_K; 277 member_params.prim_hash_seed = rte_rdtsc(); 278 params->setsum[SKETCH_BYTE] = rte_member_create(&member_params); 279 if (params->setsum[SKETCH_BYTE] == NULL) 280 fprintf(stderr, "sketch create fail\n"); 281 282 283 for (i = 0; i < NUM_TYPE; i++) { 284 if (params->setsum[i] == NULL) 285 return -1; 286 } 287 288 return 0; 289 } 290 291 static int 292 timed_adds(struct member_perf_params *params, int type) 293 { 294 const uint64_t start_tsc = rte_rdtsc(); 295 unsigned int i, a; 296 int32_t ret; 297 298 for (i = 0; i < KEYS_TO_ADD; i++) { 299 ret = rte_member_add(params->setsum[type], &keys[i], 300 data[type][i]); 301 if (ret < 0) { 302 printf("Error %d in rte_member_add - key=0x", ret); 303 for (a = 0; a < params->key_size; a++) 304 printf("%02x", keys[i][a]); 305 printf(" value=%d, type: %d\n", data[type][i], type); 306 307 return -1; 308 } 309 } 310 311 const uint64_t end_tsc = rte_rdtsc(); 312 const uint64_t time_taken = end_tsc - start_tsc; 313 314 cycles[type][params->cycle][ADD] = time_taken / KEYS_TO_ADD; 315 return 0; 316 } 317 318 static int 319 timed_adds_sketch(struct member_perf_params *params, int type) 320 { 321 const uint64_t start_tsc = rte_rdtsc(); 322 unsigned int i, j, a; 323 int32_t ret; 324 325 for (i = 0; i < NUM_ADDS / KEYS_TO_ADD; i++) { 326 for (j = 0; j < KEYS_TO_ADD; j++) { 327 if (type == SKETCH_BYTE) 328 ret = rte_member_add_byte_count(params->setsum[type], 329 &hh_keys[j], SKETCH_PKT_SIZE); 330 else 331 ret = rte_member_add(params->setsum[type], &hh_keys[j], 1); 332 if (ret < 0) { 333 printf("Error %d in rte_member_add - key=0x", ret); 334 for (a = 0; a < params->key_size; a++) 335 printf("%02x", hh_keys[j][a]); 336 printf("type: %d\n", type); 337 338 return -1; 339 } 340 } 341 } 342 343 const uint64_t end_tsc = rte_rdtsc(); 344 const uint64_t time_taken = end_tsc - start_tsc; 345 346 cycles[type][params->cycle][ADD] = time_taken / NUM_ADDS; 347 348 return 0; 349 } 350 351 static int 352 timed_lookups(struct member_perf_params *params, int type) 353 { 354 unsigned int i, j; 355 356 false_data[type][params->cycle] = 0; 357 358 const uint64_t start_tsc = rte_rdtsc(); 359 member_set_t result; 360 int ret; 361 362 for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) { 363 for (j = 0; j < KEYS_TO_ADD; j++) { 364 ret = rte_member_lookup(params->setsum[type], &keys[j], 365 &result); 366 if (ret < 0) { 367 printf("lookup wrong internally"); 368 return -1; 369 } 370 if (type == HT && result == RTE_MEMBER_NO_MATCH) { 371 printf("HT mode shouldn't have false negative"); 372 return -1; 373 } 374 if (result != data[type][j]) 375 false_data[type][params->cycle]++; 376 } 377 } 378 379 const uint64_t end_tsc = rte_rdtsc(); 380 const uint64_t time_taken = end_tsc - start_tsc; 381 382 cycles[type][params->cycle][LOOKUP] = time_taken / NUM_LOOKUPS; 383 384 return 0; 385 } 386 387 static int 388 timed_lookups_sketch(struct member_perf_params *params, int type) 389 { 390 unsigned int i, j; 391 392 false_data[type][params->cycle] = 0; 393 394 const uint64_t start_tsc = rte_rdtsc(); 395 member_set_t result; 396 int ret; 397 398 for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) { 399 for (j = 0; j < KEYS_TO_ADD; j++) { 400 ret = rte_member_lookup(params->setsum[type], &hh_keys[j], 401 &result); 402 if (ret < 0) { 403 printf("lookup wrong internally"); 404 return -1; 405 } 406 } 407 } 408 409 const uint64_t end_tsc = rte_rdtsc(); 410 const uint64_t time_taken = end_tsc - start_tsc; 411 412 cycles[type][params->cycle][LOOKUP] = time_taken / NUM_LOOKUPS; 413 414 return 0; 415 } 416 417 static int 418 timed_lookups_bulk(struct member_perf_params *params, int type) 419 { 420 unsigned int i, j, k; 421 member_set_t result[BURST_SIZE] = {0}; 422 const void *keys_burst[BURST_SIZE]; 423 int ret; 424 425 false_data_bulk[type][params->cycle] = 0; 426 427 const uint64_t start_tsc = rte_rdtsc(); 428 429 for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) { 430 for (j = 0; j < KEYS_TO_ADD / BURST_SIZE; j++) { 431 for (k = 0; k < BURST_SIZE; k++) 432 keys_burst[k] = keys[j * BURST_SIZE + k]; 433 434 ret = rte_member_lookup_bulk(params->setsum[type], 435 keys_burst, 436 BURST_SIZE, 437 result); 438 if (ret <= 0) { 439 printf("lookup bulk has wrong return value\n"); 440 return -1; 441 } 442 for (k = 0; k < BURST_SIZE; k++) { 443 uint32_t data_idx = j * BURST_SIZE + k; 444 if (type == HT && result[k] == 445 RTE_MEMBER_NO_MATCH) { 446 printf("HT mode shouldn't have " 447 "false negative"); 448 return -1; 449 } 450 if (result[k] != data[type][data_idx]) 451 false_data_bulk[type][params->cycle]++; 452 } 453 } 454 } 455 456 const uint64_t end_tsc = rte_rdtsc(); 457 const uint64_t time_taken = end_tsc - start_tsc; 458 459 cycles[type][params->cycle][LOOKUP_BULK] = time_taken / NUM_LOOKUPS; 460 461 return 0; 462 } 463 464 static int 465 timed_lookups_multimatch(struct member_perf_params *params, int type) 466 { 467 unsigned int i, j; 468 member_set_t result[RTE_MEMBER_BUCKET_ENTRIES] = {0}; 469 int ret; 470 false_data_multi[type][params->cycle] = 0; 471 472 const uint64_t start_tsc = rte_rdtsc(); 473 474 for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) { 475 for (j = 0; j < KEYS_TO_ADD; j++) { 476 ret = rte_member_lookup_multi(params->setsum[type], 477 &keys[j], RTE_MEMBER_BUCKET_ENTRIES, result); 478 if (type != CACHE && ret <= 0) { 479 printf("lookup multi has wrong return value %d," 480 "type %d\n", ret, type); 481 } 482 if (type == HT && ret == 0) { 483 printf("HT mode shouldn't have false negative"); 484 return -1; 485 } 486 /* 487 * For performance test purpose, we do not iterate all 488 * results here. We assume most likely each key can only 489 * find one match which is result[0]. 490 */ 491 if (result[0] != data[type][j]) 492 false_data_multi[type][params->cycle]++; 493 } 494 } 495 496 const uint64_t end_tsc = rte_rdtsc(); 497 const uint64_t time_taken = end_tsc - start_tsc; 498 499 cycles[type][params->cycle][LOOKUP_MULTI] = time_taken / NUM_LOOKUPS; 500 501 return 0; 502 } 503 504 static int 505 timed_lookups_multimatch_bulk(struct member_perf_params *params, int type) 506 { 507 unsigned int i, j, k; 508 member_set_t result[BURST_SIZE][RTE_MEMBER_BUCKET_ENTRIES] = {{0} }; 509 const void *keys_burst[BURST_SIZE]; 510 uint32_t match_count[BURST_SIZE]; 511 int ret; 512 513 false_data_multi_bulk[type][params->cycle] = 0; 514 515 const uint64_t start_tsc = rte_rdtsc(); 516 517 for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) { 518 for (j = 0; j < KEYS_TO_ADD / BURST_SIZE; j++) { 519 for (k = 0; k < BURST_SIZE; k++) 520 keys_burst[k] = keys[j * BURST_SIZE + k]; 521 522 ret = rte_member_lookup_multi_bulk( 523 params->setsum[type], 524 keys_burst, BURST_SIZE, 525 RTE_MEMBER_BUCKET_ENTRIES, match_count, 526 (member_set_t *)result); 527 if (ret < 0) { 528 printf("lookup multimatch bulk has wrong return" 529 " value\n"); 530 return -1; 531 } 532 for (k = 0; k < BURST_SIZE; k++) { 533 if (type != CACHE && match_count[k] == 0) { 534 printf("lookup multimatch bulk get " 535 "wrong match count\n"); 536 return -1; 537 } 538 if (type == HT && match_count[k] == 0) { 539 printf("HT mode shouldn't have " 540 "false negative"); 541 return -1; 542 } 543 uint32_t data_idx = j * BURST_SIZE + k; 544 if (result[k][0] != data[type][data_idx]) 545 false_data_multi_bulk[type][params->cycle]++; 546 } 547 } 548 } 549 550 const uint64_t end_tsc = rte_rdtsc(); 551 const uint64_t time_taken = end_tsc - start_tsc; 552 553 cycles[type][params->cycle][LOOKUP_MULTI_BULK] = time_taken / 554 NUM_LOOKUPS; 555 556 return 0; 557 } 558 559 static int 560 timed_deletes(struct member_perf_params *params, int type) 561 { 562 unsigned int i; 563 int32_t ret; 564 565 if (type == VBF) 566 return 0; 567 const uint64_t start_tsc = rte_rdtsc(); 568 for (i = 0; i < KEYS_TO_ADD; i++) { 569 ret = rte_member_delete(params->setsum[type], &keys[i], 570 data[type][i]); 571 if (type != CACHE && ret < 0) { 572 printf("delete error\n"); 573 return -1; 574 } 575 } 576 577 const uint64_t end_tsc = rte_rdtsc(); 578 const uint64_t time_taken = end_tsc - start_tsc; 579 580 cycles[type][params->cycle][DELETE] = time_taken / KEYS_TO_ADD; 581 582 return 0; 583 } 584 585 static int 586 timed_miss_lookup(struct member_perf_params *params, int type) 587 { 588 unsigned int i, j; 589 int ret; 590 591 false_hit[type][params->cycle] = 0; 592 593 for (i = 0; i < KEYS_TO_ADD / 2; i++) { 594 ret = rte_member_add(params->setsum[type], &keys[i], 595 data[type][i]); 596 if (ret < 0) { 597 unsigned int a; 598 printf("Error %d in rte_member_add - key=0x", ret); 599 for (a = 0; a < params->key_size; a++) 600 printf("%02x", keys[i][a]); 601 printf(" value=%d, type: %d\n", data[type][i], type); 602 603 return -1; 604 } 605 } 606 607 const uint64_t start_tsc = rte_rdtsc(); 608 member_set_t result; 609 610 for (i = 0; i < 2 * NUM_LOOKUPS / KEYS_TO_ADD; i++) { 611 for (j = KEYS_TO_ADD / 2; j < KEYS_TO_ADD; j++) { 612 ret = rte_member_lookup(params->setsum[type], &keys[j], 613 &result); 614 if (ret < 0) { 615 printf("lookup wrong internally"); 616 return -1; 617 } 618 if (result != RTE_MEMBER_NO_MATCH) 619 false_hit[type][params->cycle]++; 620 } 621 } 622 623 const uint64_t end_tsc = rte_rdtsc(); 624 const uint64_t time_taken = end_tsc - start_tsc; 625 626 cycles[type][params->cycle][LOOKUP_MISS] = time_taken / NUM_LOOKUPS; 627 628 return 0; 629 } 630 631 static void 632 perform_frees(struct member_perf_params *params) 633 { 634 int i; 635 for (i = 0; i < NUM_TYPE; i++) { 636 if (params->setsum[i] != NULL) { 637 rte_member_free(params->setsum[i]); 638 params->setsum[i] = NULL; 639 } 640 } 641 } 642 643 static int 644 exit_with_fail(const char *testname, struct member_perf_params *params, 645 unsigned int i, unsigned int j) 646 { 647 printf("<<<<<Test %s failed at keysize %d iteration %d type %d>>>>>\n", 648 testname, hashtest_key_lens[params->cycle], i, j); 649 perform_frees(params); 650 return -1; 651 } 652 653 static int 654 run_all_tbl_perf_tests(void) 655 { 656 unsigned int i, j, k; 657 struct member_perf_params params; 658 659 printf("Measuring performance, please wait\n"); 660 fflush(stdout); 661 662 test_socket_id = rte_socket_id(); 663 664 for (i = 0; i < NUM_KEYSIZES; i++) { 665 if (setup_keys_and_data(¶ms, i, 0) < 0) { 666 printf("Could not create keys/data/table\n"); 667 return -1; 668 } 669 for (j = 0; j < SKETCH; j++) { 670 671 if (timed_adds(¶ms, j) < 0) 672 return exit_with_fail("timed_adds", ¶ms, 673 i, j); 674 675 for (k = 0; k < NUM_SHUFFLES; k++) 676 shuffle_input_keys(¶ms); 677 678 if (timed_lookups(¶ms, j) < 0) 679 return exit_with_fail("timed_lookups", ¶ms, 680 i, j); 681 682 if (timed_lookups_bulk(¶ms, j) < 0) 683 return exit_with_fail("timed_lookups_bulk", 684 ¶ms, i, j); 685 686 if (timed_lookups_multimatch(¶ms, j) < 0) 687 return exit_with_fail("timed_lookups_multi", 688 ¶ms, i, j); 689 690 if (timed_lookups_multimatch_bulk(¶ms, j) < 0) 691 return exit_with_fail("timed_lookups_multi_bulk", 692 ¶ms, i, j); 693 694 if (timed_deletes(¶ms, j) < 0) 695 return exit_with_fail("timed_deletes", ¶ms, 696 i, j); 697 698 /* Print a dot to show progress on operations */ 699 } 700 701 for (j = SKETCH; j < NUM_TYPE; j++) { 702 if (timed_adds_sketch(¶ms, j) < 0) 703 return exit_with_fail 704 ("timed_adds_sketch", ¶ms, i, j); 705 706 if (timed_lookups_sketch(¶ms, j) < 0) 707 return exit_with_fail 708 ("timed_lookups_sketch", ¶ms, i, j); 709 } 710 711 printf("."); 712 fflush(stdout); 713 714 perform_frees(¶ms); 715 } 716 717 /* Test false positive rate using un-inserted keys */ 718 for (i = 0; i < NUM_KEYSIZES; i++) { 719 if (setup_keys_and_data(¶ms, i, 1) < 0) { 720 printf("Could not create keys/data/table\n"); 721 return -1; 722 } 723 for (j = 0; j < SKETCH; j++) { 724 if (timed_miss_lookup(¶ms, j) < 0) 725 return exit_with_fail("timed_miss_lookup", 726 ¶ms, i, j); 727 } 728 perform_frees(¶ms); 729 } 730 731 printf("\nResults (in CPU cycles/operation)\n"); 732 printf("-----------------------------------\n"); 733 printf("\n%-18s%-18s%-18s%-18s%-18s%-18s%-18s%-18s%-18s\n", 734 "Keysize", "type", "Add", "Lookup", "Lookup_bulk", 735 "lookup_multi", "lookup_multi_bulk", "Delete", 736 "miss_lookup"); 737 for (i = 0; i < NUM_KEYSIZES; i++) { 738 for (j = 0; j < NUM_TYPE; j++) { 739 printf("%-18d", hashtest_key_lens[i]); 740 printf("%-18d", j); 741 for (k = 0; k < NUM_OPERATIONS; k++) 742 printf("%-18"PRIu64, cycles[j][i][k]); 743 printf("\n"); 744 } 745 } 746 747 printf("\nFalse results rate (and false positive rate)\n"); 748 printf("-----------------------------------\n"); 749 printf("\n%-18s%-18s%-18s%-18s%-18s%-18s%-18s\n", 750 "Keysize", "type", "fr_single", "fr_bulk", "fr_multi", 751 "fr_multi_bulk", "false_positive_rate"); 752 /* Key size not influence False rate so just print out one key size */ 753 for (i = 0; i < 1; i++) { 754 for (j = 0; j < SKETCH; j++) { 755 printf("%-18d", hashtest_key_lens[i]); 756 printf("%-18d", j); 757 printf("%-18f", (float)false_data[j][i] / NUM_LOOKUPS); 758 printf("%-18f", (float)false_data_bulk[j][i] / 759 NUM_LOOKUPS); 760 printf("%-18f", (float)false_data_multi[j][i] / 761 NUM_LOOKUPS); 762 printf("%-18f", (float)false_data_multi_bulk[j][i] / 763 NUM_LOOKUPS); 764 printf("%-18f", (float)false_hit[j][i] / 765 NUM_LOOKUPS); 766 printf("\n"); 767 } 768 } 769 return 0; 770 } 771 772 static int 773 test_member_perf(void) 774 { 775 776 if (run_all_tbl_perf_tests() < 0) 777 return -1; 778 779 return 0; 780 } 781 782 #endif /* !RTE_EXEC_ENV_WINDOWS */ 783 784 REGISTER_TEST_COMMAND(member_perf_autotest, test_member_perf); 785