xref: /f-stack/dpdk/app/test/test_hash_readwrite.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright(c) 2018 Intel Corporation
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang #include <inttypes.h>
64418919fSjohnjiang #include <locale.h>
74418919fSjohnjiang 
84418919fSjohnjiang #include <rte_cycles.h>
94418919fSjohnjiang #include <rte_hash.h>
104418919fSjohnjiang #include <rte_hash_crc.h>
114418919fSjohnjiang #include <rte_jhash.h>
124418919fSjohnjiang #include <rte_launch.h>
134418919fSjohnjiang #include <rte_malloc.h>
144418919fSjohnjiang #include <rte_random.h>
154418919fSjohnjiang #include <rte_spinlock.h>
164418919fSjohnjiang 
174418919fSjohnjiang #include "test.h"
184418919fSjohnjiang 
194418919fSjohnjiang #define RTE_RWTEST_FAIL 0
204418919fSjohnjiang 
214418919fSjohnjiang #define TOTAL_ENTRY (5*1024*1024)
224418919fSjohnjiang #define TOTAL_INSERT (4.5*1024*1024)
234418919fSjohnjiang #define TOTAL_INSERT_EXT (5*1024*1024)
244418919fSjohnjiang 
254418919fSjohnjiang #define NUM_TEST 3
264418919fSjohnjiang unsigned int core_cnt[NUM_TEST] = {2, 4, 8};
274418919fSjohnjiang 
28*2d9fd380Sjfb8856606 unsigned int worker_core_ids[RTE_MAX_LCORE];
294418919fSjohnjiang struct perf {
304418919fSjohnjiang 	uint32_t single_read;
314418919fSjohnjiang 	uint32_t single_write;
324418919fSjohnjiang 	uint32_t read_only[NUM_TEST];
334418919fSjohnjiang 	uint32_t write_only[NUM_TEST];
344418919fSjohnjiang 	uint32_t read_write_r[NUM_TEST];
354418919fSjohnjiang 	uint32_t read_write_w[NUM_TEST];
364418919fSjohnjiang };
374418919fSjohnjiang 
384418919fSjohnjiang static struct perf htm_results, non_htm_results;
394418919fSjohnjiang 
404418919fSjohnjiang struct {
414418919fSjohnjiang 	uint32_t *keys;
424418919fSjohnjiang 	uint8_t *found;
434418919fSjohnjiang 	uint32_t num_insert;
444418919fSjohnjiang 	uint32_t rounded_tot_insert;
454418919fSjohnjiang 	struct rte_hash *h;
464418919fSjohnjiang } tbl_rw_test_param;
474418919fSjohnjiang 
484418919fSjohnjiang static rte_atomic64_t gcycles;
494418919fSjohnjiang static rte_atomic64_t ginsertions;
504418919fSjohnjiang 
514418919fSjohnjiang static rte_atomic64_t gread_cycles;
524418919fSjohnjiang static rte_atomic64_t gwrite_cycles;
534418919fSjohnjiang 
544418919fSjohnjiang static rte_atomic64_t greads;
554418919fSjohnjiang static rte_atomic64_t gwrites;
564418919fSjohnjiang 
574418919fSjohnjiang static int
test_hash_readwrite_worker(__rte_unused void * arg)58*2d9fd380Sjfb8856606 test_hash_readwrite_worker(__rte_unused void *arg)
594418919fSjohnjiang {
604418919fSjohnjiang 	uint64_t i, offset;
614418919fSjohnjiang 	uint32_t lcore_id = rte_lcore_id();
624418919fSjohnjiang 	uint64_t begin, cycles;
634418919fSjohnjiang 	int *ret;
644418919fSjohnjiang 
654418919fSjohnjiang 	ret = rte_malloc(NULL, sizeof(int) *
664418919fSjohnjiang 				tbl_rw_test_param.num_insert, 0);
674418919fSjohnjiang 	for (i = 0; i < rte_lcore_count(); i++) {
68*2d9fd380Sjfb8856606 		if (worker_core_ids[i] == lcore_id)
694418919fSjohnjiang 			break;
704418919fSjohnjiang 	}
714418919fSjohnjiang 	offset = tbl_rw_test_param.num_insert * i;
724418919fSjohnjiang 
734418919fSjohnjiang 	printf("Core #%d inserting and reading %d: %'"PRId64" - %'"PRId64"\n",
744418919fSjohnjiang 	       lcore_id, tbl_rw_test_param.num_insert,
754418919fSjohnjiang 	       offset, offset + tbl_rw_test_param.num_insert - 1);
764418919fSjohnjiang 
774418919fSjohnjiang 	begin = rte_rdtsc_precise();
784418919fSjohnjiang 
794418919fSjohnjiang 	for (i = offset; i < offset + tbl_rw_test_param.num_insert; i++) {
804418919fSjohnjiang 
814418919fSjohnjiang 		if (rte_hash_lookup(tbl_rw_test_param.h,
824418919fSjohnjiang 				tbl_rw_test_param.keys + i) > 0)
834418919fSjohnjiang 			break;
844418919fSjohnjiang 
854418919fSjohnjiang 		ret[i - offset] = rte_hash_add_key(tbl_rw_test_param.h,
864418919fSjohnjiang 				     tbl_rw_test_param.keys + i);
874418919fSjohnjiang 		if (ret[i - offset] < 0)
884418919fSjohnjiang 			break;
894418919fSjohnjiang 
904418919fSjohnjiang 		/* lookup a random key */
914418919fSjohnjiang 		uint32_t rand = rte_rand() % (i + 1 - offset);
924418919fSjohnjiang 
934418919fSjohnjiang 		if (rte_hash_lookup(tbl_rw_test_param.h,
944418919fSjohnjiang 				tbl_rw_test_param.keys + rand) != ret[rand])
954418919fSjohnjiang 			break;
964418919fSjohnjiang 
974418919fSjohnjiang 
984418919fSjohnjiang 		if (rte_hash_del_key(tbl_rw_test_param.h,
994418919fSjohnjiang 				tbl_rw_test_param.keys + rand) != ret[rand])
1004418919fSjohnjiang 			break;
1014418919fSjohnjiang 
1024418919fSjohnjiang 		ret[rand] = rte_hash_add_key(tbl_rw_test_param.h,
1034418919fSjohnjiang 					tbl_rw_test_param.keys + rand);
1044418919fSjohnjiang 		if (ret[rand] < 0)
1054418919fSjohnjiang 			break;
1064418919fSjohnjiang 
1074418919fSjohnjiang 		if (rte_hash_lookup(tbl_rw_test_param.h,
1084418919fSjohnjiang 			tbl_rw_test_param.keys + rand) != ret[rand])
1094418919fSjohnjiang 			break;
1104418919fSjohnjiang 	}
1114418919fSjohnjiang 
1124418919fSjohnjiang 	cycles = rte_rdtsc_precise() - begin;
1134418919fSjohnjiang 	rte_atomic64_add(&gcycles, cycles);
1144418919fSjohnjiang 	rte_atomic64_add(&ginsertions, i - offset);
1154418919fSjohnjiang 
1164418919fSjohnjiang 	for (; i < offset + tbl_rw_test_param.num_insert; i++)
1174418919fSjohnjiang 		tbl_rw_test_param.keys[i] = RTE_RWTEST_FAIL;
1184418919fSjohnjiang 
1194418919fSjohnjiang 	rte_free(ret);
1204418919fSjohnjiang 	return 0;
1214418919fSjohnjiang }
1224418919fSjohnjiang 
1234418919fSjohnjiang static int
init_params(int use_ext,int use_htm,int rw_lf,int use_jhash)124*2d9fd380Sjfb8856606 init_params(int use_ext, int use_htm, int rw_lf, int use_jhash)
1254418919fSjohnjiang {
1264418919fSjohnjiang 	unsigned int i;
1274418919fSjohnjiang 
1284418919fSjohnjiang 	uint32_t *keys = NULL;
1294418919fSjohnjiang 	uint8_t *found = NULL;
1304418919fSjohnjiang 	struct rte_hash *handle;
1314418919fSjohnjiang 
1324418919fSjohnjiang 	struct rte_hash_parameters hash_params = {
1334418919fSjohnjiang 		.entries = TOTAL_ENTRY,
1344418919fSjohnjiang 		.key_len = sizeof(uint32_t),
1354418919fSjohnjiang 		.hash_func_init_val = 0,
1364418919fSjohnjiang 		.socket_id = rte_socket_id(),
1374418919fSjohnjiang 	};
1384418919fSjohnjiang 	if (use_jhash)
1394418919fSjohnjiang 		hash_params.hash_func = rte_jhash;
1404418919fSjohnjiang 	else
1414418919fSjohnjiang 		hash_params.hash_func = rte_hash_crc;
1424418919fSjohnjiang 
143*2d9fd380Sjfb8856606 	hash_params.extra_flag = RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
1444418919fSjohnjiang 	if (use_htm)
145*2d9fd380Sjfb8856606 		hash_params.extra_flag |=
146*2d9fd380Sjfb8856606 			RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT;
147*2d9fd380Sjfb8856606 	if (rw_lf)
148*2d9fd380Sjfb8856606 		hash_params.extra_flag |=
149*2d9fd380Sjfb8856606 			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
1504418919fSjohnjiang 	else
151*2d9fd380Sjfb8856606 		hash_params.extra_flag |=
152*2d9fd380Sjfb8856606 			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY;
1534418919fSjohnjiang 
1544418919fSjohnjiang 	if (use_ext)
1554418919fSjohnjiang 		hash_params.extra_flag |=
1564418919fSjohnjiang 			RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1574418919fSjohnjiang 	else
1584418919fSjohnjiang 		hash_params.extra_flag &=
1594418919fSjohnjiang 		       ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1604418919fSjohnjiang 
1614418919fSjohnjiang 	hash_params.name = "tests";
1624418919fSjohnjiang 
1634418919fSjohnjiang 	handle = rte_hash_create(&hash_params);
1644418919fSjohnjiang 	if (handle == NULL) {
1654418919fSjohnjiang 		printf("hash creation failed");
1664418919fSjohnjiang 		return -1;
1674418919fSjohnjiang 	}
1684418919fSjohnjiang 
1694418919fSjohnjiang 	tbl_rw_test_param.h = handle;
1704418919fSjohnjiang 	keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_ENTRY, 0);
1714418919fSjohnjiang 
1724418919fSjohnjiang 	if (keys == NULL) {
1734418919fSjohnjiang 		printf("RTE_MALLOC failed\n");
1744418919fSjohnjiang 		goto err;
1754418919fSjohnjiang 	}
1764418919fSjohnjiang 
1774418919fSjohnjiang 	found = rte_zmalloc(NULL, sizeof(uint8_t) * TOTAL_ENTRY, 0);
1784418919fSjohnjiang 	if (found == NULL) {
1794418919fSjohnjiang 		printf("RTE_ZMALLOC failed\n");
1804418919fSjohnjiang 		goto err;
1814418919fSjohnjiang 	}
1824418919fSjohnjiang 
1834418919fSjohnjiang 	tbl_rw_test_param.keys = keys;
1844418919fSjohnjiang 	tbl_rw_test_param.found = found;
1854418919fSjohnjiang 
1864418919fSjohnjiang 	for (i = 0; i < TOTAL_ENTRY; i++)
1874418919fSjohnjiang 		keys[i] = i;
1884418919fSjohnjiang 
1894418919fSjohnjiang 	return 0;
1904418919fSjohnjiang 
1914418919fSjohnjiang err:
1924418919fSjohnjiang 	rte_free(keys);
1934418919fSjohnjiang 	rte_hash_free(handle);
1944418919fSjohnjiang 
1954418919fSjohnjiang 	return -1;
1964418919fSjohnjiang }
1974418919fSjohnjiang 
1984418919fSjohnjiang static int
test_hash_readwrite_functional(int use_htm,int use_rw_lf,int use_ext)199*2d9fd380Sjfb8856606 test_hash_readwrite_functional(int use_htm, int use_rw_lf, int use_ext)
2004418919fSjohnjiang {
2014418919fSjohnjiang 	unsigned int i;
2024418919fSjohnjiang 	const void *next_key;
2034418919fSjohnjiang 	void *next_data;
2044418919fSjohnjiang 	uint32_t iter = 0;
2054418919fSjohnjiang 
2064418919fSjohnjiang 	uint32_t duplicated_keys = 0;
2074418919fSjohnjiang 	uint32_t lost_keys = 0;
2084418919fSjohnjiang 	int use_jhash = 1;
209*2d9fd380Sjfb8856606 	int worker_cnt = rte_lcore_count() - 1;
2104418919fSjohnjiang 	uint32_t tot_insert = 0;
2114418919fSjohnjiang 
2124418919fSjohnjiang 	rte_atomic64_init(&gcycles);
2134418919fSjohnjiang 	rte_atomic64_clear(&gcycles);
2144418919fSjohnjiang 
2154418919fSjohnjiang 	rte_atomic64_init(&ginsertions);
2164418919fSjohnjiang 	rte_atomic64_clear(&ginsertions);
2174418919fSjohnjiang 
218*2d9fd380Sjfb8856606 	if (init_params(use_ext, use_htm, use_rw_lf, use_jhash) != 0)
2194418919fSjohnjiang 		goto err;
2204418919fSjohnjiang 
2214418919fSjohnjiang 	if (use_ext)
2224418919fSjohnjiang 		tot_insert = TOTAL_INSERT_EXT;
2234418919fSjohnjiang 	else
2244418919fSjohnjiang 		tot_insert = TOTAL_INSERT;
2254418919fSjohnjiang 
2264418919fSjohnjiang 	tbl_rw_test_param.num_insert =
227*2d9fd380Sjfb8856606 		tot_insert / worker_cnt;
2284418919fSjohnjiang 
2294418919fSjohnjiang 	tbl_rw_test_param.rounded_tot_insert =
230*2d9fd380Sjfb8856606 		tbl_rw_test_param.num_insert * worker_cnt;
2314418919fSjohnjiang 
232*2d9fd380Sjfb8856606 	printf("\nHTM = %d, RW-LF = %d, EXT-Table = %d\n",
233*2d9fd380Sjfb8856606 		use_htm, use_rw_lf, use_ext);
2344418919fSjohnjiang 	printf("++++++++Start function tests:+++++++++\n");
2354418919fSjohnjiang 
2364418919fSjohnjiang 	/* Fire all threads. */
2374418919fSjohnjiang 	rte_eal_mp_remote_launch(test_hash_readwrite_worker,
238*2d9fd380Sjfb8856606 				 NULL, SKIP_MAIN);
2394418919fSjohnjiang 	rte_eal_mp_wait_lcore();
2404418919fSjohnjiang 
2414418919fSjohnjiang 	while (rte_hash_iterate(tbl_rw_test_param.h, &next_key,
2424418919fSjohnjiang 			&next_data, &iter) >= 0) {
2434418919fSjohnjiang 		/* Search for the key in the list of keys added .*/
2444418919fSjohnjiang 		i = *(const uint32_t *)next_key;
2454418919fSjohnjiang 		tbl_rw_test_param.found[i]++;
2464418919fSjohnjiang 	}
2474418919fSjohnjiang 
2484418919fSjohnjiang 	for (i = 0; i < tbl_rw_test_param.rounded_tot_insert; i++) {
2494418919fSjohnjiang 		if (tbl_rw_test_param.keys[i] != RTE_RWTEST_FAIL) {
2504418919fSjohnjiang 			if (tbl_rw_test_param.found[i] > 1) {
2514418919fSjohnjiang 				duplicated_keys++;
2524418919fSjohnjiang 				break;
2534418919fSjohnjiang 			}
2544418919fSjohnjiang 			if (tbl_rw_test_param.found[i] == 0) {
2554418919fSjohnjiang 				lost_keys++;
2564418919fSjohnjiang 				printf("key %d is lost\n", i);
2574418919fSjohnjiang 				break;
2584418919fSjohnjiang 			}
2594418919fSjohnjiang 		}
2604418919fSjohnjiang 	}
2614418919fSjohnjiang 
2624418919fSjohnjiang 	if (duplicated_keys > 0) {
2634418919fSjohnjiang 		printf("%d key duplicated\n", duplicated_keys);
2644418919fSjohnjiang 		goto err_free;
2654418919fSjohnjiang 	}
2664418919fSjohnjiang 
2674418919fSjohnjiang 	if (lost_keys > 0) {
2684418919fSjohnjiang 		printf("%d key lost\n", lost_keys);
2694418919fSjohnjiang 		goto err_free;
2704418919fSjohnjiang 	}
2714418919fSjohnjiang 
2724418919fSjohnjiang 	printf("No key corrupted during read-write test.\n");
2734418919fSjohnjiang 
2744418919fSjohnjiang 	unsigned long long int cycles_per_insertion =
2754418919fSjohnjiang 		rte_atomic64_read(&gcycles) /
2764418919fSjohnjiang 		rte_atomic64_read(&ginsertions);
2774418919fSjohnjiang 
2784418919fSjohnjiang 	printf("cycles per insertion and lookup: %llu\n", cycles_per_insertion);
2794418919fSjohnjiang 
2804418919fSjohnjiang 	rte_free(tbl_rw_test_param.found);
2814418919fSjohnjiang 	rte_free(tbl_rw_test_param.keys);
2824418919fSjohnjiang 	rte_hash_free(tbl_rw_test_param.h);
2834418919fSjohnjiang 	printf("+++++++++Complete function tests+++++++++\n");
2844418919fSjohnjiang 	return 0;
2854418919fSjohnjiang 
2864418919fSjohnjiang err_free:
2874418919fSjohnjiang 	rte_free(tbl_rw_test_param.found);
2884418919fSjohnjiang 	rte_free(tbl_rw_test_param.keys);
2894418919fSjohnjiang 	rte_hash_free(tbl_rw_test_param.h);
2904418919fSjohnjiang err:
2914418919fSjohnjiang 	return -1;
2924418919fSjohnjiang }
2934418919fSjohnjiang 
2944418919fSjohnjiang static int
test_rw_reader(void * arg)2954418919fSjohnjiang test_rw_reader(void *arg)
2964418919fSjohnjiang {
2974418919fSjohnjiang 	uint64_t i;
2984418919fSjohnjiang 	uint64_t begin, cycles;
2994418919fSjohnjiang 	uint64_t read_cnt = (uint64_t)((uintptr_t)arg);
3004418919fSjohnjiang 
3014418919fSjohnjiang 	begin = rte_rdtsc_precise();
3024418919fSjohnjiang 	for (i = 0; i < read_cnt; i++) {
3034418919fSjohnjiang 		void *data = arg;
3044418919fSjohnjiang 		rte_hash_lookup_data(tbl_rw_test_param.h,
3054418919fSjohnjiang 				tbl_rw_test_param.keys + i,
3064418919fSjohnjiang 				&data);
3074418919fSjohnjiang 		if (i != (uint64_t)(uintptr_t)data) {
3084418919fSjohnjiang 			printf("lookup find wrong value %"PRIu64","
3094418919fSjohnjiang 				"%"PRIu64"\n", i,
3104418919fSjohnjiang 				(uint64_t)(uintptr_t)data);
3114418919fSjohnjiang 			break;
3124418919fSjohnjiang 		}
3134418919fSjohnjiang 	}
3144418919fSjohnjiang 
3154418919fSjohnjiang 	cycles = rte_rdtsc_precise() - begin;
3164418919fSjohnjiang 	rte_atomic64_add(&gread_cycles, cycles);
3174418919fSjohnjiang 	rte_atomic64_add(&greads, i);
3184418919fSjohnjiang 	return 0;
3194418919fSjohnjiang }
3204418919fSjohnjiang 
3214418919fSjohnjiang static int
test_rw_writer(void * arg)3224418919fSjohnjiang test_rw_writer(void *arg)
3234418919fSjohnjiang {
3244418919fSjohnjiang 	uint64_t i;
3254418919fSjohnjiang 	uint32_t lcore_id = rte_lcore_id();
3264418919fSjohnjiang 	uint64_t begin, cycles;
3274418919fSjohnjiang 	int ret;
3284418919fSjohnjiang 	uint64_t start_coreid = (uint64_t)(uintptr_t)arg;
3294418919fSjohnjiang 	uint64_t offset;
3304418919fSjohnjiang 
3314418919fSjohnjiang 	for (i = 0; i < rte_lcore_count(); i++) {
332*2d9fd380Sjfb8856606 		if (worker_core_ids[i] == lcore_id)
3334418919fSjohnjiang 			break;
3344418919fSjohnjiang 	}
3354418919fSjohnjiang 
3364418919fSjohnjiang 	offset = TOTAL_INSERT / 2 + (i - (start_coreid)) *
3374418919fSjohnjiang 				tbl_rw_test_param.num_insert;
3384418919fSjohnjiang 	begin = rte_rdtsc_precise();
3394418919fSjohnjiang 	for (i = offset; i < offset + tbl_rw_test_param.num_insert; i++) {
3404418919fSjohnjiang 		ret = rte_hash_add_key_data(tbl_rw_test_param.h,
3414418919fSjohnjiang 				tbl_rw_test_param.keys + i,
3424418919fSjohnjiang 				(void *)((uintptr_t)i));
3434418919fSjohnjiang 		if (ret < 0) {
3444418919fSjohnjiang 			printf("writer failed %"PRIu64"\n", i);
3454418919fSjohnjiang 			break;
3464418919fSjohnjiang 		}
3474418919fSjohnjiang 	}
3484418919fSjohnjiang 
3494418919fSjohnjiang 	cycles = rte_rdtsc_precise() - begin;
3504418919fSjohnjiang 	rte_atomic64_add(&gwrite_cycles, cycles);
3514418919fSjohnjiang 	rte_atomic64_add(&gwrites, tbl_rw_test_param.num_insert);
3524418919fSjohnjiang 	return 0;
3534418919fSjohnjiang }
3544418919fSjohnjiang 
3554418919fSjohnjiang static int
test_hash_readwrite_perf(struct perf * perf_results,int use_htm,int reader_faster)3564418919fSjohnjiang test_hash_readwrite_perf(struct perf *perf_results, int use_htm,
3574418919fSjohnjiang 							int reader_faster)
3584418919fSjohnjiang {
3594418919fSjohnjiang 	unsigned int n;
3604418919fSjohnjiang 	int ret;
3614418919fSjohnjiang 	int start_coreid;
3624418919fSjohnjiang 	uint64_t i, read_cnt;
3634418919fSjohnjiang 
3644418919fSjohnjiang 	const void *next_key;
3654418919fSjohnjiang 	void *next_data;
3664418919fSjohnjiang 	uint32_t iter;
3674418919fSjohnjiang 	int use_jhash = 0;
3684418919fSjohnjiang 
3694418919fSjohnjiang 	uint32_t duplicated_keys = 0;
3704418919fSjohnjiang 	uint32_t lost_keys = 0;
3714418919fSjohnjiang 
3724418919fSjohnjiang 	uint64_t start = 0, end = 0;
3734418919fSjohnjiang 
3744418919fSjohnjiang 	rte_atomic64_init(&greads);
3754418919fSjohnjiang 	rte_atomic64_init(&gwrites);
3764418919fSjohnjiang 	rte_atomic64_clear(&gwrites);
3774418919fSjohnjiang 	rte_atomic64_clear(&greads);
3784418919fSjohnjiang 
3794418919fSjohnjiang 	rte_atomic64_init(&gread_cycles);
3804418919fSjohnjiang 	rte_atomic64_clear(&gread_cycles);
3814418919fSjohnjiang 	rte_atomic64_init(&gwrite_cycles);
3824418919fSjohnjiang 	rte_atomic64_clear(&gwrite_cycles);
3834418919fSjohnjiang 
384*2d9fd380Sjfb8856606 	if (init_params(0, use_htm, 0, use_jhash) != 0)
3854418919fSjohnjiang 		goto err;
3864418919fSjohnjiang 
3874418919fSjohnjiang 	/*
3884418919fSjohnjiang 	 * Do a readers finish faster or writers finish faster test.
3894418919fSjohnjiang 	 * When readers finish faster, we timing the readers, and when writers
3904418919fSjohnjiang 	 * finish faster, we timing the writers.
3914418919fSjohnjiang 	 * Divided by 10 or 2 is just experimental values to vary the workload
3924418919fSjohnjiang 	 * of readers.
3934418919fSjohnjiang 	 */
3944418919fSjohnjiang 	if (reader_faster) {
3954418919fSjohnjiang 		printf("++++++Start perf test: reader++++++++\n");
3964418919fSjohnjiang 		read_cnt = TOTAL_INSERT / 10;
3974418919fSjohnjiang 	} else {
3984418919fSjohnjiang 		printf("++++++Start perf test: writer++++++++\n");
3994418919fSjohnjiang 		read_cnt = TOTAL_INSERT / 2;
4004418919fSjohnjiang 	}
4014418919fSjohnjiang 
4024418919fSjohnjiang 	/* We first test single thread performance */
4034418919fSjohnjiang 	start = rte_rdtsc_precise();
4044418919fSjohnjiang 	/* Insert half of the keys */
4054418919fSjohnjiang 	for (i = 0; i < TOTAL_INSERT / 2; i++) {
4064418919fSjohnjiang 		ret = rte_hash_add_key_data(tbl_rw_test_param.h,
4074418919fSjohnjiang 				     tbl_rw_test_param.keys + i,
4084418919fSjohnjiang 					(void *)((uintptr_t)i));
4094418919fSjohnjiang 		if (ret < 0) {
4104418919fSjohnjiang 			printf("Failed to insert half of keys\n");
4114418919fSjohnjiang 			goto err_free;
4124418919fSjohnjiang 		}
4134418919fSjohnjiang 	}
4144418919fSjohnjiang 	end = rte_rdtsc_precise() - start;
4154418919fSjohnjiang 	perf_results->single_write = end / i;
4164418919fSjohnjiang 
4174418919fSjohnjiang 	start = rte_rdtsc_precise();
4184418919fSjohnjiang 
4194418919fSjohnjiang 	for (i = 0; i < read_cnt; i++) {
4204418919fSjohnjiang 		void *data;
4214418919fSjohnjiang 		rte_hash_lookup_data(tbl_rw_test_param.h,
4224418919fSjohnjiang 				tbl_rw_test_param.keys + i,
4234418919fSjohnjiang 				&data);
4244418919fSjohnjiang 		if (i != (uint64_t)(uintptr_t)data) {
4254418919fSjohnjiang 			printf("lookup find wrong value"
4264418919fSjohnjiang 					" %"PRIu64",%"PRIu64"\n", i,
4274418919fSjohnjiang 					(uint64_t)(uintptr_t)data);
4284418919fSjohnjiang 			break;
4294418919fSjohnjiang 		}
4304418919fSjohnjiang 	}
4314418919fSjohnjiang 	end = rte_rdtsc_precise() - start;
4324418919fSjohnjiang 	perf_results->single_read = end / i;
4334418919fSjohnjiang 
4344418919fSjohnjiang 	for (n = 0; n < NUM_TEST; n++) {
435*2d9fd380Sjfb8856606 		unsigned int tot_worker_lcore = rte_lcore_count() - 1;
436*2d9fd380Sjfb8856606 		if (tot_worker_lcore < core_cnt[n] * 2)
4374418919fSjohnjiang 			goto finish;
4384418919fSjohnjiang 
4394418919fSjohnjiang 		rte_atomic64_clear(&greads);
4404418919fSjohnjiang 		rte_atomic64_clear(&gread_cycles);
4414418919fSjohnjiang 		rte_atomic64_clear(&gwrites);
4424418919fSjohnjiang 		rte_atomic64_clear(&gwrite_cycles);
4434418919fSjohnjiang 
4444418919fSjohnjiang 		rte_hash_reset(tbl_rw_test_param.h);
4454418919fSjohnjiang 
4464418919fSjohnjiang 		tbl_rw_test_param.num_insert = TOTAL_INSERT / 2 / core_cnt[n];
4474418919fSjohnjiang 		tbl_rw_test_param.rounded_tot_insert = TOTAL_INSERT / 2 +
4484418919fSjohnjiang 						tbl_rw_test_param.num_insert *
4494418919fSjohnjiang 						core_cnt[n];
4504418919fSjohnjiang 
4514418919fSjohnjiang 		for (i = 0; i < TOTAL_INSERT / 2; i++) {
4524418919fSjohnjiang 			ret = rte_hash_add_key_data(tbl_rw_test_param.h,
4534418919fSjohnjiang 					tbl_rw_test_param.keys + i,
4544418919fSjohnjiang 					(void *)((uintptr_t)i));
4554418919fSjohnjiang 			if (ret < 0) {
4564418919fSjohnjiang 				printf("Failed to insert half of keys\n");
4574418919fSjohnjiang 				goto err_free;
4584418919fSjohnjiang 			}
4594418919fSjohnjiang 		}
4604418919fSjohnjiang 
4614418919fSjohnjiang 		/* Then test multiple thread case but only all reads or
4624418919fSjohnjiang 		 * all writes
4634418919fSjohnjiang 		 */
4644418919fSjohnjiang 
4654418919fSjohnjiang 		/* Test only reader cases */
4664418919fSjohnjiang 		for (i = 0; i < core_cnt[n]; i++)
4674418919fSjohnjiang 			rte_eal_remote_launch(test_rw_reader,
4684418919fSjohnjiang 					(void *)(uintptr_t)read_cnt,
469*2d9fd380Sjfb8856606 					worker_core_ids[i]);
4704418919fSjohnjiang 
4714418919fSjohnjiang 		rte_eal_mp_wait_lcore();
4724418919fSjohnjiang 
4734418919fSjohnjiang 		start_coreid = i;
4744418919fSjohnjiang 		/* Test only writer cases */
4754418919fSjohnjiang 		for (; i < core_cnt[n] * 2; i++)
4764418919fSjohnjiang 			rte_eal_remote_launch(test_rw_writer,
4774418919fSjohnjiang 					(void *)((uintptr_t)start_coreid),
478*2d9fd380Sjfb8856606 					worker_core_ids[i]);
4794418919fSjohnjiang 
4804418919fSjohnjiang 		rte_eal_mp_wait_lcore();
4814418919fSjohnjiang 
4824418919fSjohnjiang 		if (reader_faster) {
4834418919fSjohnjiang 			unsigned long long int cycles_per_insertion =
4844418919fSjohnjiang 				rte_atomic64_read(&gread_cycles) /
4854418919fSjohnjiang 				rte_atomic64_read(&greads);
4864418919fSjohnjiang 			perf_results->read_only[n] = cycles_per_insertion;
4874418919fSjohnjiang 			printf("Reader only: cycles per lookup: %llu\n",
4884418919fSjohnjiang 							cycles_per_insertion);
4894418919fSjohnjiang 		}
4904418919fSjohnjiang 
4914418919fSjohnjiang 		else {
4924418919fSjohnjiang 			unsigned long long int cycles_per_insertion =
4934418919fSjohnjiang 				rte_atomic64_read(&gwrite_cycles) /
4944418919fSjohnjiang 				rte_atomic64_read(&gwrites);
4954418919fSjohnjiang 			perf_results->write_only[n] = cycles_per_insertion;
4964418919fSjohnjiang 			printf("Writer only: cycles per writes: %llu\n",
4974418919fSjohnjiang 							cycles_per_insertion);
4984418919fSjohnjiang 		}
4994418919fSjohnjiang 
5004418919fSjohnjiang 		rte_atomic64_clear(&greads);
5014418919fSjohnjiang 		rte_atomic64_clear(&gread_cycles);
5024418919fSjohnjiang 		rte_atomic64_clear(&gwrites);
5034418919fSjohnjiang 		rte_atomic64_clear(&gwrite_cycles);
5044418919fSjohnjiang 
5054418919fSjohnjiang 		rte_hash_reset(tbl_rw_test_param.h);
5064418919fSjohnjiang 
5074418919fSjohnjiang 		for (i = 0; i < TOTAL_INSERT / 2; i++) {
5084418919fSjohnjiang 			ret = rte_hash_add_key_data(tbl_rw_test_param.h,
5094418919fSjohnjiang 					tbl_rw_test_param.keys + i,
5104418919fSjohnjiang 					(void *)((uintptr_t)i));
5114418919fSjohnjiang 			if (ret < 0) {
5124418919fSjohnjiang 				printf("Failed to insert half of keys\n");
5134418919fSjohnjiang 				goto err_free;
5144418919fSjohnjiang 			}
5154418919fSjohnjiang 		}
5164418919fSjohnjiang 
5174418919fSjohnjiang 		start_coreid = core_cnt[n];
5184418919fSjohnjiang 
5194418919fSjohnjiang 		if (reader_faster) {
5204418919fSjohnjiang 			for (i = core_cnt[n]; i < core_cnt[n] * 2; i++)
5214418919fSjohnjiang 				rte_eal_remote_launch(test_rw_writer,
5224418919fSjohnjiang 					(void *)((uintptr_t)start_coreid),
523*2d9fd380Sjfb8856606 					worker_core_ids[i]);
5244418919fSjohnjiang 			for (i = 0; i < core_cnt[n]; i++)
5254418919fSjohnjiang 				rte_eal_remote_launch(test_rw_reader,
5264418919fSjohnjiang 					(void *)(uintptr_t)read_cnt,
527*2d9fd380Sjfb8856606 					worker_core_ids[i]);
5284418919fSjohnjiang 		} else {
5294418919fSjohnjiang 			for (i = 0; i < core_cnt[n]; i++)
5304418919fSjohnjiang 				rte_eal_remote_launch(test_rw_reader,
5314418919fSjohnjiang 					(void *)(uintptr_t)read_cnt,
532*2d9fd380Sjfb8856606 					worker_core_ids[i]);
5334418919fSjohnjiang 			for (; i < core_cnt[n] * 2; i++)
5344418919fSjohnjiang 				rte_eal_remote_launch(test_rw_writer,
5354418919fSjohnjiang 					(void *)((uintptr_t)start_coreid),
536*2d9fd380Sjfb8856606 					worker_core_ids[i]);
5374418919fSjohnjiang 		}
5384418919fSjohnjiang 
5394418919fSjohnjiang 		rte_eal_mp_wait_lcore();
5404418919fSjohnjiang 
5414418919fSjohnjiang 		iter = 0;
5424418919fSjohnjiang 		memset(tbl_rw_test_param.found, 0, TOTAL_ENTRY);
5434418919fSjohnjiang 		while (rte_hash_iterate(tbl_rw_test_param.h,
5444418919fSjohnjiang 				&next_key, &next_data, &iter) >= 0) {
5454418919fSjohnjiang 			/* Search for the key in the list of keys added .*/
5464418919fSjohnjiang 			i = *(const uint32_t *)next_key;
5474418919fSjohnjiang 			tbl_rw_test_param.found[i]++;
5484418919fSjohnjiang 		}
5494418919fSjohnjiang 
5504418919fSjohnjiang 		for (i = 0; i < tbl_rw_test_param.rounded_tot_insert; i++) {
5514418919fSjohnjiang 			if (tbl_rw_test_param.keys[i] != RTE_RWTEST_FAIL) {
5524418919fSjohnjiang 				if (tbl_rw_test_param.found[i] > 1) {
5534418919fSjohnjiang 					duplicated_keys++;
5544418919fSjohnjiang 					break;
5554418919fSjohnjiang 				}
5564418919fSjohnjiang 				if (tbl_rw_test_param.found[i] == 0) {
5574418919fSjohnjiang 					lost_keys++;
5584418919fSjohnjiang 					printf("key %"PRIu64" is lost\n", i);
5594418919fSjohnjiang 					break;
5604418919fSjohnjiang 				}
5614418919fSjohnjiang 			}
5624418919fSjohnjiang 		}
5634418919fSjohnjiang 
5644418919fSjohnjiang 		if (duplicated_keys > 0) {
5654418919fSjohnjiang 			printf("%d key duplicated\n", duplicated_keys);
5664418919fSjohnjiang 			goto err_free;
5674418919fSjohnjiang 		}
5684418919fSjohnjiang 
5694418919fSjohnjiang 		if (lost_keys > 0) {
5704418919fSjohnjiang 			printf("%d key lost\n", lost_keys);
5714418919fSjohnjiang 			goto err_free;
5724418919fSjohnjiang 		}
5734418919fSjohnjiang 
5744418919fSjohnjiang 		printf("No key corrupted during read-write test.\n");
5754418919fSjohnjiang 
5764418919fSjohnjiang 		if (reader_faster) {
5774418919fSjohnjiang 			unsigned long long int cycles_per_insertion =
5784418919fSjohnjiang 				rte_atomic64_read(&gread_cycles) /
5794418919fSjohnjiang 				rte_atomic64_read(&greads);
5804418919fSjohnjiang 			perf_results->read_write_r[n] = cycles_per_insertion;
5814418919fSjohnjiang 			printf("Read-write cycles per lookup: %llu\n",
5824418919fSjohnjiang 							cycles_per_insertion);
5834418919fSjohnjiang 		}
5844418919fSjohnjiang 
5854418919fSjohnjiang 		else {
5864418919fSjohnjiang 			unsigned long long int cycles_per_insertion =
5874418919fSjohnjiang 				rte_atomic64_read(&gwrite_cycles) /
5884418919fSjohnjiang 				rte_atomic64_read(&gwrites);
5894418919fSjohnjiang 			perf_results->read_write_w[n] = cycles_per_insertion;
5904418919fSjohnjiang 			printf("Read-write cycles per writes: %llu\n",
5914418919fSjohnjiang 							cycles_per_insertion);
5924418919fSjohnjiang 		}
5934418919fSjohnjiang 	}
5944418919fSjohnjiang 
5954418919fSjohnjiang finish:
5964418919fSjohnjiang 	rte_free(tbl_rw_test_param.found);
5974418919fSjohnjiang 	rte_free(tbl_rw_test_param.keys);
5984418919fSjohnjiang 	rte_hash_free(tbl_rw_test_param.h);
5994418919fSjohnjiang 	return 0;
6004418919fSjohnjiang 
6014418919fSjohnjiang err_free:
6024418919fSjohnjiang 	rte_free(tbl_rw_test_param.found);
6034418919fSjohnjiang 	rte_free(tbl_rw_test_param.keys);
6044418919fSjohnjiang 	rte_hash_free(tbl_rw_test_param.h);
6054418919fSjohnjiang 
6064418919fSjohnjiang err:
6074418919fSjohnjiang 	return -1;
6084418919fSjohnjiang }
6094418919fSjohnjiang 
6104418919fSjohnjiang static int
test_hash_rw_perf_main(void)611*2d9fd380Sjfb8856606 test_hash_rw_perf_main(void)
6124418919fSjohnjiang {
6134418919fSjohnjiang 	/*
6144418919fSjohnjiang 	 * Variables used to choose different tests.
6154418919fSjohnjiang 	 * use_htm indicates if hardware transactional memory should be used.
6164418919fSjohnjiang 	 * reader_faster indicates if the reader threads should finish earlier
6174418919fSjohnjiang 	 * than writer threads. This is to timing either reader threads or
6184418919fSjohnjiang 	 * writer threads for performance numbers.
6194418919fSjohnjiang 	 */
620*2d9fd380Sjfb8856606 	int use_htm, reader_faster;
6214418919fSjohnjiang 	unsigned int i = 0, core_id = 0;
6224418919fSjohnjiang 
6234418919fSjohnjiang 	if (rte_lcore_count() < 3) {
6244418919fSjohnjiang 		printf("Not enough cores for hash_readwrite_autotest, expecting at least 3\n");
6254418919fSjohnjiang 		return TEST_SKIPPED;
6264418919fSjohnjiang 	}
6274418919fSjohnjiang 
628*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(core_id) {
629*2d9fd380Sjfb8856606 		worker_core_ids[i] = core_id;
6304418919fSjohnjiang 		i++;
6314418919fSjohnjiang 	}
6324418919fSjohnjiang 
6334418919fSjohnjiang 	setlocale(LC_NUMERIC, "");
6344418919fSjohnjiang 
6354418919fSjohnjiang 	if (rte_tm_supported()) {
6364418919fSjohnjiang 		printf("Hardware transactional memory (lock elision) "
6374418919fSjohnjiang 			"is supported\n");
6384418919fSjohnjiang 
6394418919fSjohnjiang 		printf("Test read-write with Hardware transactional memory\n");
6404418919fSjohnjiang 
6414418919fSjohnjiang 		use_htm = 1;
6424418919fSjohnjiang 
6434418919fSjohnjiang 		reader_faster = 1;
6444418919fSjohnjiang 		if (test_hash_readwrite_perf(&htm_results, use_htm,
6454418919fSjohnjiang 							reader_faster) < 0)
6464418919fSjohnjiang 			return -1;
6474418919fSjohnjiang 
6484418919fSjohnjiang 		reader_faster = 0;
6494418919fSjohnjiang 		if (test_hash_readwrite_perf(&htm_results, use_htm,
6504418919fSjohnjiang 							reader_faster) < 0)
6514418919fSjohnjiang 			return -1;
6524418919fSjohnjiang 	} else {
6534418919fSjohnjiang 		printf("Hardware transactional memory (lock elision) "
6544418919fSjohnjiang 			"is NOT supported\n");
6554418919fSjohnjiang 	}
6564418919fSjohnjiang 
6574418919fSjohnjiang 	printf("Test read-write without Hardware transactional memory\n");
6584418919fSjohnjiang 	use_htm = 0;
6594418919fSjohnjiang 
6604418919fSjohnjiang 	reader_faster = 1;
6614418919fSjohnjiang 	if (test_hash_readwrite_perf(&non_htm_results, use_htm,
6624418919fSjohnjiang 							reader_faster) < 0)
6634418919fSjohnjiang 		return -1;
6644418919fSjohnjiang 	reader_faster = 0;
6654418919fSjohnjiang 	if (test_hash_readwrite_perf(&non_htm_results, use_htm,
6664418919fSjohnjiang 							reader_faster) < 0)
6674418919fSjohnjiang 		return -1;
6684418919fSjohnjiang 
6694418919fSjohnjiang 	printf("================\n");
6704418919fSjohnjiang 	printf("Results summary:\n");
6714418919fSjohnjiang 	printf("================\n");
6724418919fSjohnjiang 
6734418919fSjohnjiang 	printf("single read: %u\n", htm_results.single_read);
6744418919fSjohnjiang 	printf("single write: %u\n", htm_results.single_write);
6754418919fSjohnjiang 	for (i = 0; i < NUM_TEST; i++) {
6764418919fSjohnjiang 		printf("+++ core_cnt: %u +++\n", core_cnt[i]);
6774418919fSjohnjiang 		printf("HTM:\n");
6784418919fSjohnjiang 		printf("  read only: %u\n", htm_results.read_only[i]);
6794418919fSjohnjiang 		printf("  write only: %u\n", htm_results.write_only[i]);
6804418919fSjohnjiang 		printf("  read-write read: %u\n", htm_results.read_write_r[i]);
6814418919fSjohnjiang 		printf("  read-write write: %u\n", htm_results.read_write_w[i]);
6824418919fSjohnjiang 
6834418919fSjohnjiang 		printf("non HTM:\n");
6844418919fSjohnjiang 		printf("  read only: %u\n", non_htm_results.read_only[i]);
6854418919fSjohnjiang 		printf("  write only: %u\n", non_htm_results.write_only[i]);
6864418919fSjohnjiang 		printf("  read-write read: %u\n",
6874418919fSjohnjiang 			non_htm_results.read_write_r[i]);
6884418919fSjohnjiang 		printf("  read-write write: %u\n",
6894418919fSjohnjiang 			non_htm_results.read_write_w[i]);
6904418919fSjohnjiang 	}
6914418919fSjohnjiang 
6924418919fSjohnjiang 	return 0;
6934418919fSjohnjiang }
6944418919fSjohnjiang 
695*2d9fd380Sjfb8856606 static int
test_hash_rw_func_main(void)696*2d9fd380Sjfb8856606 test_hash_rw_func_main(void)
697*2d9fd380Sjfb8856606 {
698*2d9fd380Sjfb8856606 	/*
699*2d9fd380Sjfb8856606 	 * Variables used to choose different tests.
700*2d9fd380Sjfb8856606 	 * use_htm indicates if hardware transactional memory should be used.
701*2d9fd380Sjfb8856606 	 * reader_faster indicates if the reader threads should finish earlier
702*2d9fd380Sjfb8856606 	 * than writer threads. This is to timing either reader threads or
703*2d9fd380Sjfb8856606 	 * writer threads for performance numbers.
704*2d9fd380Sjfb8856606 	 */
705*2d9fd380Sjfb8856606 	unsigned int i = 0, core_id = 0;
706*2d9fd380Sjfb8856606 
707*2d9fd380Sjfb8856606 	if (rte_lcore_count() < 3) {
708*2d9fd380Sjfb8856606 		printf("Not enough cores for hash_readwrite_autotest, expecting at least 3\n");
709*2d9fd380Sjfb8856606 		return TEST_SKIPPED;
710*2d9fd380Sjfb8856606 	}
711*2d9fd380Sjfb8856606 
712*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(core_id) {
713*2d9fd380Sjfb8856606 		worker_core_ids[i] = core_id;
714*2d9fd380Sjfb8856606 		i++;
715*2d9fd380Sjfb8856606 	}
716*2d9fd380Sjfb8856606 
717*2d9fd380Sjfb8856606 	setlocale(LC_NUMERIC, "");
718*2d9fd380Sjfb8856606 
719*2d9fd380Sjfb8856606 	if (rte_tm_supported()) {
720*2d9fd380Sjfb8856606 		printf("Hardware transactional memory (lock elision) "
721*2d9fd380Sjfb8856606 			"is supported\n");
722*2d9fd380Sjfb8856606 
723*2d9fd380Sjfb8856606 		printf("Test read-write with Hardware transactional memory\n");
724*2d9fd380Sjfb8856606 
725*2d9fd380Sjfb8856606 		/* htm = 1, rw_lf = 0, ext = 0 */
726*2d9fd380Sjfb8856606 		if (test_hash_readwrite_functional(1, 0, 0) < 0)
727*2d9fd380Sjfb8856606 			return -1;
728*2d9fd380Sjfb8856606 
729*2d9fd380Sjfb8856606 		/* htm = 1, rw_lf = 1, ext = 0 */
730*2d9fd380Sjfb8856606 		if (test_hash_readwrite_functional(1, 1, 0) < 0)
731*2d9fd380Sjfb8856606 			return -1;
732*2d9fd380Sjfb8856606 
733*2d9fd380Sjfb8856606 		/* htm = 1, rw_lf = 0, ext = 1 */
734*2d9fd380Sjfb8856606 		if (test_hash_readwrite_functional(1, 0, 1) < 0)
735*2d9fd380Sjfb8856606 			return -1;
736*2d9fd380Sjfb8856606 
737*2d9fd380Sjfb8856606 		/* htm = 1, rw_lf = 1, ext = 1 */
738*2d9fd380Sjfb8856606 		if (test_hash_readwrite_functional(1, 1, 1) < 0)
739*2d9fd380Sjfb8856606 			return -1;
740*2d9fd380Sjfb8856606 	} else {
741*2d9fd380Sjfb8856606 		printf("Hardware transactional memory (lock elision) "
742*2d9fd380Sjfb8856606 			"is NOT supported\n");
743*2d9fd380Sjfb8856606 	}
744*2d9fd380Sjfb8856606 
745*2d9fd380Sjfb8856606 	printf("Test read-write without Hardware transactional memory\n");
746*2d9fd380Sjfb8856606 	/* htm = 0, rw_lf = 0, ext = 0 */
747*2d9fd380Sjfb8856606 	if (test_hash_readwrite_functional(0, 0, 0) < 0)
748*2d9fd380Sjfb8856606 		return -1;
749*2d9fd380Sjfb8856606 
750*2d9fd380Sjfb8856606 	/* htm = 0, rw_lf = 1, ext = 0 */
751*2d9fd380Sjfb8856606 	if (test_hash_readwrite_functional(0, 1, 0) < 0)
752*2d9fd380Sjfb8856606 		return -1;
753*2d9fd380Sjfb8856606 
754*2d9fd380Sjfb8856606 	/* htm = 0, rw_lf = 0, ext = 1 */
755*2d9fd380Sjfb8856606 	if (test_hash_readwrite_functional(0, 0, 1) < 0)
756*2d9fd380Sjfb8856606 		return -1;
757*2d9fd380Sjfb8856606 
758*2d9fd380Sjfb8856606 	/* htm = 0, rw_lf = 1, ext = 1 */
759*2d9fd380Sjfb8856606 	if (test_hash_readwrite_functional(0, 1, 1) < 0)
760*2d9fd380Sjfb8856606 		return -1;
761*2d9fd380Sjfb8856606 
762*2d9fd380Sjfb8856606 	return 0;
763*2d9fd380Sjfb8856606 }
764*2d9fd380Sjfb8856606 
765*2d9fd380Sjfb8856606 REGISTER_TEST_COMMAND(hash_readwrite_func_autotest, test_hash_rw_func_main);
766*2d9fd380Sjfb8856606 REGISTER_TEST_COMMAND(hash_readwrite_perf_autotest, test_hash_rw_perf_main);
767