diff options
| author | liuyu <[email protected]> | 2024-07-07 20:56:29 +0800 |
|---|---|---|
| committer | liuyu <[email protected]> | 2024-07-07 20:56:29 +0800 |
| commit | 4d5c9b6f26237c4b5f61da362e9decb7bf83ddf4 (patch) | |
| tree | 7edfb8c4845444a39a62f0e0762ccb9a651829c3 | |
| parent | 87e474bc378fcbda10ad041c3fe3d1e2159fbd43 (diff) | |
临时提交,修改函数名ut_开头
| -rw-r--r-- | bbq/tests/common/test_mix.c | 176 | ||||
| -rw-r--r-- | bbq/tests/common/test_mix.h | 207 | ||||
| -rw-r--r-- | bbq/tests/common/test_queue.c | 460 | ||||
| -rw-r--r-- | bbq/tests/common/test_queue.h | 328 | ||||
| -rw-r--r-- | bbq/tests/unittest/ut.h | 20 | ||||
| -rw-r--r-- | bbq/tests/unittest/ut_example.cc | 826 | ||||
| -rw-r--r-- | bbq/tests/unittest/ut_head_cursor.cc | 550 | ||||
| -rw-r--r-- | bbq/tests/unittest/ut_mix.cc | 184 | ||||
| -rw-r--r-- | bbq/tests/unittest/ut_multit.cc | 91 | ||||
| -rw-r--r-- | perf/benchmark/bcm_benchmark.c | 69 | ||||
| -rw-r--r-- | perf/benchmark/bcm_loadconfig.c | 50 | ||||
| -rw-r--r-- | perf/benchmark/bcm_queue.c | 64 | ||||
| -rw-r--r-- | perf/benchmark/bcm_queue.h | 8 |
13 files changed, 1465 insertions, 1568 deletions
diff --git a/bbq/tests/common/test_mix.c b/bbq/tests/common/test_mix.c deleted file mode 100644 index ee0595e..0000000 --- a/bbq/tests/common/test_mix.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * @Description: 描述信息 - * @Date: 2024-05-25 10:55:48 - * @LastEditTime: 2024-07-04 06:21:46 - */ -#include "test_mix.h" -#include "bbq.h" -#include <pthread.h> -#include <string.h> -#include <sys/time.h> - -typedef struct { - aotmic_uint64 malloc_cnt; - aotmic_uint64 free_cnt; -} test_memory_s; - -test_memory_s test_memory_g[TEST_MODULE_MAX] = {0}; - -void *test_malloc(test_module_e module, size_t size) { - void *ptr = malloc(size); - if (ptr != NULL) { - atomic_fetch_add(&test_memory_g[module].malloc_cnt, 1); - } - - return ptr; -} - -void test_free(test_module_e module, void *ptr) { - if (ptr != NULL) { - atomic_fetch_add(&test_memory_g[module].free_cnt, 1); - } - free(ptr); -} - -bool test_malloc_free_equal() { - bool ret = true; - for (int i = 0; i < TEST_MODULE_MAX; i++) { - uint64_t malloc_cnt = atomic_load(&test_memory_g[i].malloc_cnt); - uint64_t free_cnt = atomic_load(&test_memory_g[i].free_cnt); - if (malloc_cnt != free_cnt) { - TEST_ERR_LOG("[module:%d] malloc:%lu free:%lu, test malloc-free not equal\n", i, malloc_cnt, free_cnt); - ret = false; - } - } - return ret; -} - -void test_memory_counter_clear() { - memset(test_memory_g, 0, sizeof(test_memory_g)); -} - -void test_memory_counter_print() { - for (int i = 0; i < TEST_MODULE_MAX; i++) { - uint64_t malloc_cnt = atomic_load(&test_memory_g[i].malloc_cnt); - uint64_t free_cnt = atomic_load(&test_memory_g[i].free_cnt); - if (malloc_cnt == 0 && free_cnt == 0) { - continue; - } - - TEST_INFO_LOG("[%d]test malloc:%lu free:%lu", i, - atomic_load(&test_memory_g[i].malloc_cnt), - atomic_load(&test_memory_g[i].free_cnt)); - } - - if (test_malloc_free_equal()) { - TEST_INFO_LOG("all memory free"); - } else { - TEST_ERR_LOG("memory not all free"); - } -} - -test_time_metric test_clock_time_get() { - test_time_metric metric = {0}; - clock_gettime(CLOCK_REALTIME, &metric.timestamp); // 系统实时时间,随系统实时时间改变而改变 - return metric; -} - -uint64_t test_clock_time_to_ns(test_time_metric *metric) { - return metric->timestamp.tv_nsec + metric->timestamp.tv_sec * 1000 * 1000 * 1000; -} - -double test_clock_time_to_double(test_time_metric *metric) { - return metric->timestamp.tv_sec + - metric->timestamp.tv_nsec * 1.0 / 1000 / 1000 / 1000; -} - -bool test_clock_time_is_zero(test_time_metric *metric) { - return metric->timestamp.tv_sec == 0 && metric->timestamp.tv_nsec == 0; -} - -bool test_timespec_is_after(const struct timespec *a, const struct timespec *b) { - if (a->tv_sec > b->tv_sec) { - // a的秒数大于b的秒数,所以a在b之后 - return true; - } else if (a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec) { - // a和b的秒数相同,但a的纳秒数大于b的纳秒数,所以a在b之后 - return true; - } - // 否则,a不在b之后 - return false; -} - -test_time_metric test_clock_time_sub(test_time_metric now, test_time_metric last) { - test_time_metric diff = { - .timestamp.tv_sec = now.timestamp.tv_sec - last.timestamp.tv_sec, - .timestamp.tv_nsec = now.timestamp.tv_nsec - last.timestamp.tv_nsec, - }; - - if (now.timestamp.tv_nsec > last.timestamp.tv_nsec) { - diff.timestamp.tv_nsec = now.timestamp.tv_nsec - last.timestamp.tv_nsec; - } else { - // 从秒借位 - diff.timestamp.tv_sec--; - diff.timestamp.tv_nsec = 1000 * 1000 * 1000 + now.timestamp.tv_nsec - last.timestamp.tv_nsec; - } - - return diff; -} - -test_workload_e test_workload_str2enum(const char *workload) { - if (strcmp(workload, "simple") == 0) { - return TEST_WORKLOAD_SIMPLE; - } else if (strcmp(workload, "complex") == 0) { - return TEST_WORKLOAD_COMPLEX; - } - - return TEST_WORKLOAD_MAX; -} - -char *ring_type_map[TEST_RING_TYPE_MAX] = { - [TEST_RING_TYPE_BBQ] = TEST_RING_TYPE_BBQ_STR, - [TEST_RING_TYPE_DPDK] = TEST_RING_TYPE_DPDK_STR, - [TEST_RING_TYPE_RMIND] = TEST_RING_TYPE_RMIND_STR, -}; - -test_ring_type test_ring_type_str2enum(const char *ring_type) { - if (strcmp(ring_type, TEST_RING_TYPE_BBQ_STR) == 0) { - return TEST_RING_TYPE_BBQ; - } else if (strcmp(ring_type, TEST_RING_TYPE_DPDK_STR) == 0) { - return TEST_RING_TYPE_DPDK; - } else if (strcmp(ring_type, TEST_RING_TYPE_RMIND_STR) == 0) { - return TEST_RING_TYPE_RMIND; - } - - return TEST_RING_TYPE_MAX; -} - -char *test_ring_type_enum2str(test_ring_type ring_type) { - if (ring_type >= TEST_RING_TYPE_MAX) { - return "unknown"; - } else { - return ring_type_map[ring_type]; - } -} - -int test_setaffinity(int core_id) { - cpu_set_t mask; - CPU_ZERO(&mask); - CPU_SET(core_id, &mask); - - if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == -1) { - TEST_ERR_LOG("pthread_setaffinity_np erro\n"); - return BBQ_ERR; - } - - return BBQ_OK; -} - -void *test_malloc_def_callback(int32_t socket_id __attribute__((unused)), size_t size) { - return aligned_alloc(BBQ_CACHE_LINE, size); -} - -void test_free_def_callback(void *ptr, - size_t size __attribute__((unused))) { - free(ptr); -}
\ No newline at end of file diff --git a/bbq/tests/common/test_mix.h b/bbq/tests/common/test_mix.h deleted file mode 100644 index 20b8f77..0000000 --- a/bbq/tests/common/test_mix.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * @Author: liuyu - * @LastEditTime: 2024-07-04 03:45:43 - * @Email: [email protected] - * @Describe: TODO - */ -#ifndef _TEST_MIX_H_ -#define _TEST_MIX_H_ - -#include <pthread.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <time.h> - -#ifndef __cplusplus -// C -#include <stdatomic.h> -#endif - -typedef enum { - TEST_THREAD_PRODUCER, - TEST_THREAD_CONSUMER, - TEST_THREAD_TYPE_MAX, -} test_thread_type_e; - -typedef struct { - struct timespec timestamp; // 系统时间戳 - // uint64_t cycles; // cpu运行的cycle -} test_time_metric; - -typedef struct { - uint64_t throughput; // 吞吐量:每秒消耗的条目总数。 - double data_latency; // 数据延迟:每个数据在队列中停留的平均时间。 - double op_latency; // 操作延迟:每个入队或出队操作的平均延迟。 - double *fairness; // 公平性:每个生产者/消费者的吞吐量(占总吞吐的百分比) - double full_empty; // 队列满时入队的延迟/队列空时出队的延迟(仅用于简单工作负载)。 - uint64_t oversubscription; // 比核心/超线程更多的生产者和消费者的吞吐量 -} test_report; - -typedef enum { - TEST_WORKLOAD_SIMPLE, // 简单负载,每个生产者或消费者都有自己的线程,它们在循环中不断执行入队或出队操作。每次出队后都会验证数据。 - TEST_WORKLOAD_COMPLEX, // 复杂负载,基于简单工作负载。生产者和消费者为数据分配空间,执行入队和出队,然后手动释放 - TEST_WORKLOAD_MAX, -} test_workload_e; - -#define TEST_RING_TYPE_BBQ_STR "bbq" -#define TEST_RING_TYPE_DPDK_STR "dpdk" -#define TEST_RING_TYPE_RMIND_STR "rmind" -typedef enum { - TEST_RING_TYPE_BBQ, - TEST_RING_TYPE_DPDK, - TEST_RING_TYPE_RMIND, - TEST_RING_TYPE_MAX, -} test_ring_type; - -typedef struct { - char name[128]; // 配置文件名 - char introduce[128]; // 测试配置说明 - uint16_t cores_cnt; // 测试用核心个数 -} test_cfg_base; - -typedef struct { - test_ring_type ring_type; // ring buffer类型 - uint32_t producer_cnt; // 生产者个数 - uint32_t consumer_cnt; // 消费者个数 - test_workload_e workload; // 负载模式 - uint64_t entries_cnt; // ring初始化时分配entry的个数 - uint32_t block_count; // bbq block个数,为0时表示根据entries_cnt自动计算 - uint32_t burst_cnt; // 批量出入队个数 -} test_cfg_ring; - -typedef struct { - uint64_t run_ok_times; // 成功入队/入队次数 - uint64_t run_time; // 整体运行时间,单位秒 -} test_cfg_run; - -typedef struct { - test_cfg_base base; - test_cfg_ring ring; - test_cfg_run run; -} test_cfg; - -typedef struct { - volatile bool running; // 默认为true,当设置为false,即所有生产者消费者即将退出 - pthread_barrier_t all_threads_start; -#ifndef __cplusplus - // C - atomic_uint producer_exit; -#else - // C++ 为了兼容gtest测试 - std::atomic<uint32_t> producer_exit; -#endif -} test_ctl; - -typedef struct { - test_cfg cfg; - test_ctl ctl; -} test_info_s; - -typedef enum { - TEST_MODULE_UTEST, - TEST_MODULE_COMMON, - TEST_MODULE_DATA, - TEST_MODULE_BCM, - TEST_MODULE_TABLE, - TEST_MODULE_RMIND, - TEST_MODULE_MAX, -} test_module_e; - -#ifdef TEST_DEBUG -#define TEST_DBG_LOG(fmt, ...) \ - do { \ - printf("[DBG][%s:%d:%s]" fmt "\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ - } while (0) - -#else -#define TEST_DBG_LOG(fmt, ...) \ - do { \ - } while (0) -#endif - -#define TEST_ERR_LOG(fmt, ...) \ - do { \ - printf("\x1b[31m [ERR][%s:%d:%s]" fmt "\x1b[0m\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ - } while (0) - -#define TEST_INFO_LOG(fmt, ...) \ - do { \ - printf("[INFO][%s:%d:%s]" fmt "\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ - } while (0) - -#define TEST_AVOID_WARNING(param) ((void)param) - -extern test_time_metric test_clock_time_get(); -extern test_time_metric test_clock_time_sub(test_time_metric now, test_time_metric last); -extern int test_load_config(const char *config, const char *ring_type, uint32_t burst_cnt, test_cfg *cfg); -extern test_workload_e test_workload_str2enum(const char *workload); -extern test_ring_type test_ring_type_str2enum(const char *ring_type); -extern bool test_clock_time_is_zero(test_time_metric *metric); -extern bool test_timespec_is_after(const struct timespec *a, const struct timespec *b); -extern char *test_ring_type_enum2str(test_ring_type ring_type); -extern uint64_t test_clock_time_to_ns(test_time_metric *metric); -extern double test_clock_time_to_double(test_time_metric *metric); -extern void *test_malloc(test_module_e module, size_t size); -extern void test_free(test_module_e module, void *ptr); -extern void test_memory_counter_print(); -extern void test_memory_counter_clear(); -extern bool test_malloc_free_equal(); -extern int test_setaffinity(int core_id); -extern void *test_malloc_def_callback(int32_t socket_id __attribute__((unused)), size_t size); -extern void test_free_def_callback(void *ptr, size_t size __attribute__((unused))); - -#define TEST_PTR_ARRAY_DATA_INIT(table, t_type, t_count) \ - do { \ - if (table != NULL) { \ - memset(table, 0, sizeof(t_type *) * t_count); \ - for (uint32_t i = 0; i < t_count; i++) { \ - table[i] = (t_type *)test_malloc(TEST_MODULE_TABLE, sizeof(t_type)); \ - if (table[i] == NULL) { \ - for (uint32_t j = 0; j < i; j++) { \ - test_free(TEST_MODULE_TABLE, table[j]); \ - table[j] = NULL; \ - } \ - test_free(TEST_MODULE_TABLE, table); \ - break; \ - } \ - *table[i] = (t_type)TEST_DATA_MAGIC; \ - } \ - } \ - } while (0) - -#define TEST_PTR_ARRAY_DATA_DESTORY(table, t_count) \ - do { \ - if (table != NULL) { \ - for (uint32_t i = 0; i < t_count; i++) { \ - test_free(TEST_MODULE_TABLE, table[i]); \ - table[i] = NULL; \ - } \ - } \ - } while (0) - -#define TEST_DOUBLE_PTR_DATA_INIT(table, t_type, t_count) \ - do { \ - table = (t_type **)test_malloc(TEST_MODULE_TABLE, sizeof(t_type *) * t_count); \ - if (table != NULL) { \ - TEST_PTR_ARRAY_DATA_INIT(table, t_type, t_count); \ - } \ - } while (0) - -#define TEST_DOUBLE_PTR_DATA_DESTORY(table, t_count) \ - do { \ - if (table != NULL) { \ - TEST_PTR_ARRAY_DATA_DESTORY(table, t_count); \ - test_free(TEST_MODULE_TABLE, table); \ - table = NULL; \ - } \ - } while (0) - -#define TEST_ARRAY_DATA_INIT(table, t_count) \ - do { \ - for (int i = 0; i < t_count; i++) { \ - table[i] = TEST_DATA_MAGIC; \ - } \ - } while (0) - -#endif
\ No newline at end of file diff --git a/bbq/tests/common/test_queue.c b/bbq/tests/common/test_queue.c index 10dd261..2b10074 100644 --- a/bbq/tests/common/test_queue.c +++ b/bbq/tests/common/test_queue.c @@ -1,15 +1,185 @@ /* * @Author: liuyu - * @LastEditTime: 2024-07-04 03:46:35 + * @LastEditTime: 2024-07-07 20:51:03 * @Email: [email protected] * @Describe: TODO */ #include "test_queue.h" #include "bbq.h" -#include "test_mix.h" +#include <pthread.h> +#include <string.h> #include <sys/prctl.h> +#include <sys/time.h> #include <unistd.h> + +typedef struct { + aotmic_uint64 malloc_cnt; + aotmic_uint64 free_cnt; +} ut_memory_s; + +ut_memory_s ut_memory_g[UT_MODULE_MAX] = {0}; + +char *ut_ring_type_map[UT_RING_TYPE_MAX] = { + [UT_RING_TYPE_BBQ] = UT_RING_TYPE_BBQ_STR, + [UT_RING_TYPE_DPDK] = UT_RING_TYPE_DPDK_STR, + [UT_RING_TYPE_RMIND] = UT_RING_TYPE_RMIND_STR, +}; + +void *ut_malloc(enum ut_module module, size_t size) { + void *ptr = malloc(size); + if (ptr != NULL) { + atomic_fetch_add(&ut_memory_g[module].malloc_cnt, 1); + } + + return ptr; +} + +void ut_free(enum ut_module module, void *ptr) { + if (ptr != NULL) { + atomic_fetch_add(&ut_memory_g[module].free_cnt, 1); + } + free(ptr); +} + +bool ut_malloc_free_equal() { + bool ret = true; + for (int i = 0; i < UT_MODULE_MAX; i++) { + uint64_t malloc_cnt = atomic_load(&ut_memory_g[i].malloc_cnt); + uint64_t free_cnt = atomic_load(&ut_memory_g[i].free_cnt); + if (malloc_cnt != free_cnt) { + UT_ERR_LOG("[module:%d] malloc:%lu free:%lu, test malloc-free not equal\n", i, malloc_cnt, free_cnt); + ret = false; + } + } + + return ret; +} + +void ut_memory_counter_clear() { + memset(ut_memory_g, 0, sizeof(ut_memory_g)); +} + +void ut_memory_counter_print() { + for (int i = 0; i < UT_MODULE_MAX; i++) { + uint64_t malloc_cnt = atomic_load(&ut_memory_g[i].malloc_cnt); + uint64_t free_cnt = atomic_load(&ut_memory_g[i].free_cnt); + if (malloc_cnt == 0 && free_cnt == 0) { + continue; + } + + UT_INFO_LOG("[%d]test malloc:%lu free:%lu", i, + atomic_load(&ut_memory_g[i].malloc_cnt), + atomic_load(&ut_memory_g[i].free_cnt)); + } + + if (ut_malloc_free_equal()) { + UT_INFO_LOG("all memory free"); + } else { + UT_ERR_LOG("memory not all free"); + } +} + +struct ut_metric ut_clock_time_get() { + struct ut_metric metric = {0}; + clock_gettime(CLOCK_REALTIME, &metric.timestamp); // 系统实时时间,随系统实时时间改变而改变 + return metric; +} + +uint64_t ut_clock_time_to_ns(struct ut_metric *metric) { + return metric->timestamp.tv_nsec + metric->timestamp.tv_sec * 1000 * 1000 * 1000; +} + +double ut_clock_time_to_double(struct ut_metric *metric) { + return metric->timestamp.tv_sec + + metric->timestamp.tv_nsec * 1.0 / 1000 / 1000 / 1000; +} + +bool ut_clock_time_is_zero(struct ut_metric *metric) { + return metric->timestamp.tv_sec == 0 && metric->timestamp.tv_nsec == 0; +} + +bool ut_timespec_is_after(const struct timespec *a, const struct timespec *b) { + if (a->tv_sec > b->tv_sec) { + // a的秒数大于b的秒数,所以a在b之后 + return true; + } else if (a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec) { + // a和b的秒数相同,但a的纳秒数大于b的纳秒数,所以a在b之后 + return true; + } + // 否则,a不在b之后 + return false; +} + +struct ut_metric ut_clock_time_sub(struct ut_metric now, struct ut_metric last) { + struct ut_metric diff = { + .timestamp.tv_sec = now.timestamp.tv_sec - last.timestamp.tv_sec, + .timestamp.tv_nsec = now.timestamp.tv_nsec - last.timestamp.tv_nsec, + }; + + if (now.timestamp.tv_nsec > last.timestamp.tv_nsec) { + diff.timestamp.tv_nsec = now.timestamp.tv_nsec - last.timestamp.tv_nsec; + } else { + // 从秒借位 + diff.timestamp.tv_sec--; + diff.timestamp.tv_nsec = 1000 * 1000 * 1000 + now.timestamp.tv_nsec - last.timestamp.tv_nsec; + } + + return diff; +} + +enum ut_workload ut_workload_str2enum(const char *workload) { + if (strcmp(workload, "simple") == 0) { + return UT_WORKLOAD_SIMPLE; + } else if (strcmp(workload, "complex") == 0) { + return UT_WORKLOAD_COMPLEX; + } + + return UT_WORKLOAD_MAX; +} + +enum ut_ring_type ut_ring_type_str2enum(const char *ring_type) { + if (strcmp(ring_type, UT_RING_TYPE_BBQ_STR) == 0) { + return UT_RING_TYPE_BBQ; + } else if (strcmp(ring_type, UT_RING_TYPE_DPDK_STR) == 0) { + return UT_RING_TYPE_DPDK; + } else if (strcmp(ring_type, UT_RING_TYPE_RMIND_STR) == 0) { + return UT_RING_TYPE_RMIND; + } + + return UT_RING_TYPE_MAX; +} + +char *ut_ring_type_enum2str(enum ut_ring_type ring_type) { + if (ring_type >= UT_RING_TYPE_MAX) { + return "unknown"; + } else { + return ut_ring_type_map[ring_type]; + } +} + +int ut_setaffinity(int core_id) { + cpu_set_t mask; + CPU_ZERO(&mask); + CPU_SET(core_id, &mask); + + if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == -1) { + UT_ERR_LOG("pthread_setaffinity_np erro\n"); + return BBQ_ERR; + } + + return BBQ_OK; +} + +void *ut_malloc_def_callback(int32_t socket_id __attribute__((unused)), size_t size) { + return aligned_alloc(BBQ_CACHE_LINE, size); +} + +void ut_free_def_callback(void *ptr, + size_t size __attribute__((unused))) { + free(ptr); +} + extern bool bbq_debug_check_array_bounds(struct bbq *q); extern struct bbq *bbq_create_elem_with_bnbs(const char *name, uint32_t bn, uint32_t bs, size_t obj_size, int socket_id, uint32_t flags, @@ -18,12 +188,12 @@ extern struct bbq *bbq_create_with_bnbs(const char *name, uint32_t bn, uint32_t int socket_id, uint32_t flags, bbq_malloc_f malloc_f, bbq_free_f free_f); -uint32_t test_bbq_enqueue_burst(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed) { - TEST_AVOID_WARNING(thread_idx); +uint32_t ut_bbq_enqueue_burst(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed) { + UT_AVOID_WARNING(thread_idx); return bbq_enqueue_burst(ring, obj_table, n, wait_consumed); } -int test_queue_init_bbq(test_cfg *cfg, test_queue_s *q) { +int ut_queue_init_bbq(struct ut_cfg *cfg, struct ut_queue *q) { #if 0 // 开启了BBQ_F_ENABLE_STAT 会导致性能下降 unsigned int flags = BBQ_F_RETRY_NEW | BBQ_F_ENABLE_STAT; @@ -40,55 +210,55 @@ int test_queue_init_bbq(test_cfg *cfg, test_queue_s *q) { } if (cfg->ring.block_count == 0) { - q->ring = bbq_create("test_bbq", cfg->ring.entries_cnt, BBQ_SOCKET_ID_ANY, flags, - test_malloc_def_callback, test_free_def_callback); + q->ring = bbq_create("ut_bbq", cfg->ring.entries_cnt, BBQ_SOCKET_ID_ANY, flags, + ut_malloc_def_callback, ut_free_def_callback); } else { - q->ring = bbq_create_with_bnbs("test_bbq", cfg->ring.block_count, + q->ring = bbq_create_with_bnbs("ut_bbq", cfg->ring.block_count, cfg->ring.entries_cnt / cfg->ring.block_count, - BBQ_SOCKET_ID_ANY, flags, test_malloc_def_callback, test_free_def_callback); + BBQ_SOCKET_ID_ANY, flags, ut_malloc_def_callback, ut_free_def_callback); } if (q->ring == NULL) { - TEST_ERR_LOG("bbq create queue failed"); + UT_ERR_LOG("bbq create queue failed"); return BBQ_ERR_INPUT_NULL; } - q->ring_free_f = (test_ring_free_f)bbq_destory; - q->enqueue_f = (test_ring_enqueue_f)bbq_enqueue; - q->dequeue_f = (test_ring_dequeue_f)bbq_dequeue; - q->enqueue_burst_f = (test_enqueue_burst_f)test_bbq_enqueue_burst; - q->dequeue_burst_f = (test_dequeue_burst_f)bbq_dequeue_burst; + q->ring_free_f = (ut_ring_free_f)bbq_destory; + q->enqueue_f = (ut_ring_enqueue_f)bbq_enqueue; + q->dequeue_f = (ut_ring_dequeue_f)bbq_dequeue; + q->enqueue_burst_f = (ut_enqueue_burst_f)ut_bbq_enqueue_burst; + q->dequeue_burst_f = (ut_dequeue_burst_f)bbq_dequeue_burst; return 0; } -void test_queue_destory(test_queue_s *q) { +void ut_queue_destory(struct ut_queue *q) { if (q != NULL && q->ring_free_f != NULL) { q->ring_free_f(q->ring); } } -bool test_all_producer_exit(test_info_s *test_info) { - return atomic_load(&test_info->ctl.producer_exit) == test_info->cfg.ring.producer_cnt; +bool ut_all_producer_exit(struct ut_info_s *ut_info) { + return atomic_load(&ut_info->ctl.producer_exit) == ut_info->cfg.ring.producer_cnt; } -void test_wait_all_threads_ready(test_ctl *ctl) { +void ut_wait_all_threads_ready(struct ut_ctl *ctl) { pthread_barrier_wait(&ctl->all_threads_start); - TEST_DBG_LOG("thread init done!"); + UT_DBG_LOG("thread init done!"); } -test_exit_data *test_exit_data_create(test_thread_arg_s *t_arg) { - test_exit_data *exit_data = (test_exit_data *)test_malloc(TEST_MODULE_COMMON, sizeof(test_exit_data)); +struct ut_exit_data *ut_exit_data_create(struct ut_thread_arg *t_arg) { + struct ut_exit_data *exit_data = (struct ut_exit_data *)ut_malloc(UT_MODULE_COMMON, sizeof(struct ut_exit_data)); if (exit_data == NULL) { - TEST_ERR_LOG("malloc failed"); + UT_ERR_LOG("malloc failed"); exit(-1); } - size_t size = t_arg->test_info->cfg.ring.entries_cnt; + size_t size = t_arg->info->cfg.ring.entries_cnt; exit_data->simple_data_cnt = size; - exit_data->simple_data = test_data_create(size, TEST_DATA_MAGIC_TYPE); + exit_data->simple_data = ut_data_create(size, UT_DATA_MAGIC_TYPE); if (exit_data->simple_data == NULL) { - TEST_ERR_LOG("malloc failed"); + UT_ERR_LOG("malloc failed"); exit(-1); } exit_data->arg = t_arg; @@ -99,19 +269,19 @@ test_exit_data *test_exit_data_create(test_thread_arg_s *t_arg) { return exit_data; } -void test_exit_data_destory(test_exit_data *data) { - test_data_destory(data->simple_data, data->simple_data_cnt); - test_free(TEST_MODULE_COMMON, data->arg); - test_free(TEST_MODULE_COMMON, data); +void ut_exit_data_destory(struct ut_exit_data *data) { + ut_data_destory(data->simple_data, data->simple_data_cnt); + ut_free(UT_MODULE_COMMON, data->arg); + ut_free(UT_MODULE_COMMON, data); } -test_data **test_data_create(size_t cnt, enum test_data_type data_type) { - test_data **simple_data = test_malloc(TEST_MODULE_DATA, sizeof(*simple_data) * cnt); - test_time_metric enqueue_time = test_clock_time_get(); +struct ut_data **ut_data_create(size_t cnt, enum ut_data_type data_type) { + struct ut_data **simple_data = ut_malloc(UT_MODULE_DATA, sizeof(*simple_data) * cnt); + struct ut_metric enqueue_time = ut_clock_time_get(); for (size_t i = 0; i < cnt; i++) { - simple_data[i] = test_malloc(TEST_MODULE_DATA, sizeof(*simple_data[i])); - if (data_type == TEST_DATA_MAGIC_TYPE) { - simple_data[i]->data = TEST_DATA_MAGIC; + simple_data[i] = ut_malloc(UT_MODULE_DATA, sizeof(*simple_data[i])); + if (data_type == UT_DATA_MAGIC_TYPE) { + simple_data[i]->data = UT_DATA_MAGIC; } else { simple_data[i]->data = (uintptr_t)(simple_data[i]); } @@ -121,176 +291,176 @@ test_data **test_data_create(size_t cnt, enum test_data_type data_type) { return simple_data; } -void test_data_destory(test_data **data, size_t cnt) { +void ut_data_destory(struct ut_data **data, size_t cnt) { for (size_t i = 0; i < cnt; i++) { - test_free(TEST_MODULE_DATA, data[i]); + ut_free(UT_MODULE_DATA, data[i]); } - test_free(TEST_MODULE_DATA, data); + ut_free(UT_MODULE_DATA, data); } -uint32_t test_exec_enqueue(test_queue_s *q, test_data **data, size_t burst_cnt, - test_time_metric *op_use_diff, uint16_t thread_idx) { +uint32_t ut_exec_enqueue(struct ut_queue *q, struct ut_data **data, size_t burst_cnt, + struct ut_metric *op_use_diff, uint16_t thread_idx) { uint32_t enqueue_cnt = 0; - test_time_metric op_use_start = test_clock_time_get(); + struct ut_metric op_use_start = ut_clock_time_get(); uint32_t wait_consumed = 0; enqueue_cnt = q->enqueue_burst_f(q->ring, (void **)data, burst_cnt, thread_idx, &wait_consumed); - *op_use_diff = test_clock_time_sub(test_clock_time_get(), op_use_start); + *op_use_diff = ut_clock_time_sub(ut_clock_time_get(), op_use_start); return enqueue_cnt; } -uint32_t test_exec_dequeue(test_queue_s *q, test_data **data, size_t burst_cnt, test_time_metric *op_use_diff) { +uint32_t ut_exec_dequeue(struct ut_queue *q, struct ut_data **data, size_t burst_cnt, struct ut_metric *op_use_diff) { uint32_t dequeue_cnt = 0; - test_time_metric op_use_start = test_clock_time_get(); + struct ut_metric op_use_start = ut_clock_time_get(); dequeue_cnt = q->dequeue_burst_f(q->ring, (void **)data, burst_cnt, NULL); - *op_use_diff = test_clock_time_sub(test_clock_time_get(), op_use_start); + *op_use_diff = ut_clock_time_sub(ut_clock_time_get(), op_use_start); return dequeue_cnt; } -void *test_thread_producer_start(void *arg) { +void *ut_thread_producer_start(void *arg) { uint32_t enqueue_cnt = 0; uint64_t ok_cnt = 0; uint64_t run_times = 0; - test_thread_arg_s *t_arg = (test_thread_arg_s *)arg; - test_info_s *test_info = t_arg->test_info; - test_cfg *cfg = &test_info->cfg; - test_queue_s *q = t_arg->q; - test_exit_data *exit_data = test_exit_data_create(t_arg); + struct ut_thread_arg *t_arg = (struct ut_thread_arg *)arg; + struct ut_info_s *info = t_arg->info; + struct ut_cfg *cfg = &info->cfg; + struct ut_queue *q = t_arg->q; + struct ut_exit_data *exit_data = ut_exit_data_create(t_arg); char thread_name[128] = {0}; uint64_t op_ok_latency_ns = 0; uint64_t op_err_latency_ns = 0; uint64_t run_ok_times = cfg->run.run_ok_times / cfg->ring.producer_cnt; - test_time_metric op_latency = {0}; + struct ut_metric op_latency = {0}; snprintf(thread_name, sizeof(thread_name), "producer:%lu", exit_data->thread_id); prctl(PR_SET_NAME, thread_name); - if (test_setaffinity(t_arg->core) != BBQ_OK) { - TEST_ERR_LOG("test_setaffinity error"); + if (ut_setaffinity(t_arg->core) != BBQ_OK) { + UT_ERR_LOG("ut_setaffinity error"); exit(-1); } - test_wait_all_threads_ready(&test_info->ctl); - // TEST_INFO_LOG("producer thread:%lx, core:%d", exit_data->thread_id, t_arg->core); + ut_wait_all_threads_ready(&info->ctl); + // UT_INFO_LOG("producer thread:%lx, core:%d", exit_data->thread_id, t_arg->core); - exit_data->metric_start = test_clock_time_get(); + exit_data->metric_start = ut_clock_time_get(); while (true) { - if ((run_ok_times > 0 && ok_cnt >= run_ok_times) || (!test_info->ctl.running)) { + if ((run_ok_times > 0 && ok_cnt >= run_ok_times) || (!info->ctl.running)) { // 控制次数的循环或运行时间到了 break; } - if (cfg->ring.workload == TEST_WORKLOAD_SIMPLE) { - enqueue_cnt = test_exec_enqueue(q, exit_data->simple_data, cfg->ring.burst_cnt, &op_latency, t_arg->thread_idx); + if (cfg->ring.workload == UT_WORKLOAD_SIMPLE) { + enqueue_cnt = ut_exec_enqueue(q, exit_data->simple_data, cfg->ring.burst_cnt, &op_latency, t_arg->thread_idx); } else { - test_data **data = test_data_create(cfg->ring.burst_cnt, TEST_DATA_UINTPTR_TYPE); + struct ut_data **data = ut_data_create(cfg->ring.burst_cnt, UT_DATA_UINTPTR_TYPE); if (data == NULL) { - TEST_ERR_LOG("malloc falied"); + UT_ERR_LOG("malloc falied"); exit(-1); } - enqueue_cnt = test_exec_enqueue(q, data, cfg->ring.burst_cnt, &op_latency, t_arg->thread_idx); + enqueue_cnt = ut_exec_enqueue(q, data, cfg->ring.burst_cnt, &op_latency, t_arg->thread_idx); // 释放未入队的内存 for (uint32_t i = enqueue_cnt; i < cfg->ring.burst_cnt; i++) { - test_free(TEST_MODULE_DATA, data[i]); + ut_free(UT_MODULE_DATA, data[i]); } - test_free(TEST_MODULE_DATA, data); + ut_free(UT_MODULE_DATA, data); } if (enqueue_cnt > 0) { ok_cnt += enqueue_cnt; - op_ok_latency_ns += test_clock_time_to_ns(&op_latency); + op_ok_latency_ns += ut_clock_time_to_ns(&op_latency); } else { - op_err_latency_ns += test_clock_time_to_ns(&op_latency); + op_err_latency_ns += ut_clock_time_to_ns(&op_latency); } run_times++; } - exit_data->metric_end = test_clock_time_get(); + exit_data->metric_end = ut_clock_time_get(); exit_data->run_times = run_times; exit_data->ok_cnt = ok_cnt; exit_data->op_ok_latency_ns = op_ok_latency_ns; exit_data->op_err_latency_ns = op_err_latency_ns; - atomic_fetch_add(&test_info->ctl.producer_exit, 1); + atomic_fetch_add(&info->ctl.producer_exit, 1); - TEST_DBG_LOG("producer-----> en_ok:%lu", ok_cnt); + UT_DBG_LOG("producer-----> en_ok:%lu", ok_cnt); pthread_exit(exit_data); } -void *test_thread_consumer_start(void *arg) { +void *ut_thread_consumer_start(void *arg) { uint32_t deq_cnt = -1; uint64_t ok_cnt = 0; uint64_t run_times = 0; - test_thread_arg_s *t_arg = (test_thread_arg_s *)arg; - test_info_s *test_info = t_arg->test_info; - test_cfg *cfg = &test_info->cfg; - test_queue_s *q = t_arg->q; - test_exit_data *exit_data = test_exit_data_create(t_arg); + struct ut_thread_arg *t_arg = (struct ut_thread_arg *)arg; + struct ut_info_s *info = t_arg->info; + struct ut_cfg *cfg = &info->cfg; + struct ut_queue *q = t_arg->q; + struct ut_exit_data *exit_data = ut_exit_data_create(t_arg); uint64_t latency_ns = 0; - test_time_metric op_latency = {0}; + struct ut_metric op_latency = {0}; uint64_t op_ok_latency_ns = 0; uint64_t op_err_latency_ns = 0; uint64_t data_error_cnt = 0; char thread_name[128] = {0}; - test_data **deq_data = test_malloc(TEST_MODULE_DATA, sizeof(*deq_data) * cfg->ring.entries_cnt); + struct ut_data **deq_data = ut_malloc(UT_MODULE_DATA, sizeof(*deq_data) * cfg->ring.entries_cnt); snprintf(thread_name, sizeof(thread_name), "consumer:%lu", exit_data->thread_id); prctl(PR_SET_NAME, thread_name); - if (test_setaffinity(t_arg->core) != BBQ_OK) { - TEST_ERR_LOG("test_setaffinity error"); + if (ut_setaffinity(t_arg->core) != BBQ_OK) { + UT_ERR_LOG("ut_setaffinity error"); exit(-1); } - test_wait_all_threads_ready(&test_info->ctl); - // TEST_INFO_LOG("consumer thread:%lx, core:%d", exit_data->thread_id, t_arg->core); + ut_wait_all_threads_ready(&info->ctl); + // UT_INFO_LOG("consumer thread:%lx, core:%d", exit_data->thread_id, t_arg->core); - exit_data->metric_start = test_clock_time_get(); + exit_data->metric_start = ut_clock_time_get(); while (true) { - if (test_all_producer_exit(test_info) && deq_cnt == 0) { + if (ut_all_producer_exit(info) && deq_cnt == 0) { // 运行时间到了或是所有生产者退出了,检查生产者是否全部退出,且队列被消费完了 break; } - deq_cnt = test_exec_dequeue(q, deq_data, cfg->ring.burst_cnt, &op_latency); + deq_cnt = ut_exec_dequeue(q, deq_data, cfg->ring.burst_cnt, &op_latency); if (deq_cnt > 0) { for (uint32_t i = 0; i < deq_cnt; i++) { - test_data *data = deq_data[i]; - if (cfg->ring.workload == TEST_WORKLOAD_SIMPLE) { - if (data->data != TEST_DATA_MAGIC) { - TEST_ERR_LOG("the obtained data is not consistent with the expectation, expect:%u actual:%lu", TEST_DATA_MAGIC, data->data); + struct ut_data *data = deq_data[i]; + if (cfg->ring.workload == UT_WORKLOAD_SIMPLE) { + if (data->data != UT_DATA_MAGIC) { + UT_ERR_LOG("the obtained data is not consistent with the expectation, expect:%u actual:%lu", UT_DATA_MAGIC, data->data); exit_data->data_error_cnt += 1; } } else { - test_time_metric latency = test_clock_time_sub(test_clock_time_get(), data->enqueue_time); - if (test_clock_time_is_zero(&data->enqueue_time)) { - TEST_ERR_LOG("enqueue_time is 0"); + struct ut_metric latency = ut_clock_time_sub(ut_clock_time_get(), data->enqueue_time); + if (ut_clock_time_is_zero(&data->enqueue_time)) { + UT_ERR_LOG("enqueue_time is 0"); exit(-1); } if (data->data != (uintptr_t)data) { - TEST_ERR_LOG("the obtained data is not consistent with the expectation, expect:%lu actual:%lu", (uintptr_t)data, data->data); + UT_ERR_LOG("the obtained data is not consistent with the expectation, expect:%lu actual:%lu", (uintptr_t)data, data->data); data_error_cnt += 1; } - latency_ns += test_clock_time_to_ns(&latency); - test_free(TEST_MODULE_DATA, data); + latency_ns += ut_clock_time_to_ns(&latency); + ut_free(UT_MODULE_DATA, data); } } ok_cnt += deq_cnt; - op_ok_latency_ns += test_clock_time_to_ns(&op_latency); + op_ok_latency_ns += ut_clock_time_to_ns(&op_latency); } else { - op_err_latency_ns += test_clock_time_to_ns(&op_latency); + op_err_latency_ns += ut_clock_time_to_ns(&op_latency); } run_times++; } - exit_data->metric_end = test_clock_time_get(); + exit_data->metric_end = ut_clock_time_get(); exit_data->run_times = run_times; exit_data->ok_cnt = ok_cnt; exit_data->latency_ns = latency_ns; @@ -298,35 +468,35 @@ void *test_thread_consumer_start(void *arg) { exit_data->op_err_latency_ns = op_err_latency_ns; exit_data->data_error_cnt = data_error_cnt; - test_free(TEST_MODULE_DATA, deq_data); - TEST_DBG_LOG("consumer-----> de_ok:%lu", ok_cnt); + ut_free(UT_MODULE_DATA, deq_data); + UT_DBG_LOG("consumer-----> de_ok:%lu", ok_cnt); pthread_exit(exit_data); } -void test_wait_all_threads_exit(test_info_s *test_info, uint32_t thread_cnt, pthread_t *threads, test_exit_data **exit_data) { - if (test_info->cfg.run.run_time > 0) { - TEST_DBG_LOG("sleep %lus, and notify all threads to exit...", test_info->cfg.run.run_time); - sleep(test_info->cfg.run.run_time); - test_info->ctl.running = false; +void ut_wait_all_threads_exit(struct ut_info_s *info, uint32_t thread_cnt, pthread_t *threads, struct ut_exit_data **exit_data) { + if (info->cfg.run.run_time > 0) { + UT_DBG_LOG("sleep %lus, and notify all threads to exit...", info->cfg.run.run_time); + sleep(info->cfg.run.run_time); + info->ctl.running = false; } for (uint32_t i = 0; i < thread_cnt; i++) { pthread_join(threads[i], (void **)(&exit_data[i])); // 等待每个线程结束 } } -void test_one_thread_create(test_info_s *test_info, test_queue_s *q, test_thread_type_e ttype, int core, uint16_t thread_id, pthread_t *thread) { - TEST_DBG_LOG("thread type:%d core:%d", ttype, core); - test_thread_arg_s *arg = (test_thread_arg_s *)test_malloc(TEST_MODULE_COMMON, sizeof(test_thread_arg_s)); // 线程回收时free - arg->test_info = test_info; +void ut_one_thread_create(struct ut_info_s *info, struct ut_queue *q, enum ut_thread_type ttype, int core, uint16_t thread_id, pthread_t *thread) { + UT_DBG_LOG("thread type:%d core:%d", ttype, core); + struct ut_thread_arg *arg = (struct ut_thread_arg *)ut_malloc(UT_MODULE_COMMON, sizeof(struct ut_thread_arg)); // 线程回收时free + arg->info = info; arg->q = q; arg->ttype = ttype; arg->core = core; arg->thread_idx = thread_id; - if (ttype == TEST_THREAD_PRODUCER) { - pthread_create(thread, NULL, test_thread_producer_start, arg); + if (ttype == UT_THREAD_PRODUCER) { + pthread_create(thread, NULL, ut_thread_producer_start, arg); } else { - pthread_create(thread, NULL, test_thread_consumer_start, arg); + pthread_create(thread, NULL, ut_thread_consumer_start, arg); } } @@ -335,37 +505,37 @@ void test_one_thread_create(test_info_s *test_info, test_queue_s *q, test_thread core_id = (core_id + 1) < max_id ? (core_id + 1) : core_id; \ } while (0) -pthread_t *test_threads_create(test_info_s *test_info, test_queue_s *q) { +pthread_t *ut_threads_create(struct ut_info_s *info, struct ut_queue *q) { // 创建生产者消费者线程 uint16_t thread_id = 0; int core_id = 0; - test_cfg *cfg = &test_info->cfg; + struct ut_cfg *cfg = &info->cfg; size_t thread_cnt = cfg->ring.producer_cnt + cfg->ring.consumer_cnt; - pthread_t *threads = (pthread_t *)test_malloc(TEST_MODULE_COMMON, sizeof(pthread_t) * thread_cnt); // 存储所有线程ID的数组 + pthread_t *threads = (pthread_t *)ut_malloc(UT_MODULE_COMMON, sizeof(pthread_t) * thread_cnt); // 存储所有线程ID的数组 - pthread_barrier_init(&test_info->ctl.all_threads_start, NULL, thread_cnt); - test_info->ctl.running = true; - test_info->ctl.producer_exit = ATOMIC_VAR_INIT(0); + pthread_barrier_init(&info->ctl.all_threads_start, NULL, thread_cnt); + info->ctl.running = true; + info->ctl.producer_exit = ATOMIC_VAR_INIT(0); // MPSC 或 SPMC 场景在第一个核心/超线程上分配单个生产者或消费者,然后将其他线程按顺序分配给核心/超线程。 // MPMC,我们将生产者和消费者一一交错分配 // 如果数量不同,则在最后分配剩余部分。 if (cfg->ring.producer_cnt == 1 && cfg->ring.consumer_cnt >= 1) { // SPMC,第一个核心给生产者,其他分配给消费者 - test_one_thread_create(test_info, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); + ut_one_thread_create(info, q, UT_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); thread_id++; for (uint32_t i = 0; i < cfg->ring.consumer_cnt; i++) { CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); - test_one_thread_create(test_info, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); + ut_one_thread_create(info, q, UT_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); thread_id++; } } else if (cfg->ring.consumer_cnt == 1 && cfg->ring.producer_cnt >= 1) { // MPSC,第一个核心给消费者,其他分配给生产者 - test_one_thread_create(test_info, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); + ut_one_thread_create(info, q, UT_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); thread_id++; for (uint32_t i = 0; i < cfg->ring.producer_cnt; i++) { CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); - test_one_thread_create(test_info, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); + ut_one_thread_create(info, q, UT_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); thread_id++; } } else { @@ -375,11 +545,11 @@ pthread_t *test_threads_create(test_info_s *test_info, test_queue_s *q) { for (core_id = 0; core_id < cfg->base.cores_cnt && pcnt > 0 && ccnt > 0;) { if ((core_id & 1) == 0) { // 偶数 - test_one_thread_create(test_info, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); + ut_one_thread_create(info, q, UT_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); thread_id++; pcnt--; } else { - test_one_thread_create(test_info, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); + ut_one_thread_create(info, q, UT_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); thread_id++; ccnt--; } @@ -387,13 +557,13 @@ pthread_t *test_threads_create(test_info_s *test_info, test_queue_s *q) { } for (uint32_t i = 0; i < pcnt; i++) { - test_one_thread_create(test_info, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); + ut_one_thread_create(info, q, UT_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); thread_id++; CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); } for (uint32_t i = 0; i < ccnt; i++) { - test_one_thread_create(test_info, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); + ut_one_thread_create(info, q, UT_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); thread_id++; CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); } @@ -402,12 +572,12 @@ pthread_t *test_threads_create(test_info_s *test_info, test_queue_s *q) { return threads; } -void test_threads_destory(test_info_s *test_info, pthread_t *threads) { - pthread_barrier_destroy(&test_info->ctl.all_threads_start); - test_free(TEST_MODULE_COMMON, threads); +void ut_threads_destory(struct ut_info_s *info, pthread_t *threads) { + pthread_barrier_destroy(&info->ctl.all_threads_start); + ut_free(UT_MODULE_COMMON, threads); } -void test_merge_data_detail(test_merge_data *merge, test_exit_data *exit_data) { +void ut_merge_data_detail(struct ut_merge_data *merge, struct ut_exit_data *exit_data) { merge->run_times += exit_data->run_times; merge->ok_cnt += exit_data->ok_cnt; merge->latency_ns += exit_data->latency_ns; @@ -416,37 +586,37 @@ void test_merge_data_detail(test_merge_data *merge, test_exit_data *exit_data) { merge->data_error_cnt += exit_data->data_error_cnt; } -void test_merge_all_data(test_exit_data **exit_data, uint32_t thread_cnt, test_merge_s *merge) { - test_time_metric p_start = {0}; - test_time_metric p_end = {0}; - test_time_metric c_start = {0}; - test_time_metric c_end = {0}; +void ut_merge_all_data(struct ut_exit_data **exit_data, uint32_t thread_cnt, struct ut_merge_s *merge) { + struct ut_metric p_start = {0}; + struct ut_metric p_end = {0}; + struct ut_metric c_start = {0}; + struct ut_metric c_end = {0}; for (uint32_t i = 0; i < thread_cnt; i++) { // 根据生产者/消费者 线程最早开始和最晚结束,记录时间 - if (exit_data[i]->arg->ttype == TEST_THREAD_PRODUCER) { - if (test_clock_time_is_zero(&p_start) || test_timespec_is_after(&p_start.timestamp, &exit_data[i]->metric_start.timestamp)) { + if (exit_data[i]->arg->ttype == UT_THREAD_PRODUCER) { + if (ut_clock_time_is_zero(&p_start) || ut_timespec_is_after(&p_start.timestamp, &exit_data[i]->metric_start.timestamp)) { p_start = exit_data[i]->metric_start; } - if (test_timespec_is_after(&exit_data[i]->metric_start.timestamp, &p_end.timestamp)) { + if (ut_timespec_is_after(&exit_data[i]->metric_start.timestamp, &p_end.timestamp)) { p_end = exit_data[i]->metric_end; } - test_merge_data_detail(&merge->producer, exit_data[i]); + ut_merge_data_detail(&merge->producer, exit_data[i]); } else { - if (test_clock_time_is_zero(&c_start) || test_timespec_is_after(&c_start.timestamp, &exit_data[i]->metric_start.timestamp)) { + if (ut_clock_time_is_zero(&c_start) || ut_timespec_is_after(&c_start.timestamp, &exit_data[i]->metric_start.timestamp)) { c_start = exit_data[i]->metric_start; } - if (test_timespec_is_after(&exit_data[i]->metric_start.timestamp, &c_end.timestamp)) { + if (ut_timespec_is_after(&exit_data[i]->metric_start.timestamp, &c_end.timestamp)) { c_end = exit_data[i]->metric_end; } - test_merge_data_detail(&merge->consumer, exit_data[i]); + ut_merge_data_detail(&merge->consumer, exit_data[i]); } } - merge->producer.use_time = test_clock_time_sub(p_end, p_start); - merge->consumer.use_time = test_clock_time_sub(c_end, c_start); + merge->producer.use_time = ut_clock_time_sub(p_end, p_start); + merge->consumer.use_time = ut_clock_time_sub(c_end, c_start); }
\ No newline at end of file diff --git a/bbq/tests/common/test_queue.h b/bbq/tests/common/test_queue.h index 3fc090f..ba2ea9c 100644 --- a/bbq/tests/common/test_queue.h +++ b/bbq/tests/common/test_queue.h @@ -1,105 +1,293 @@ /* * @Author: liuyu - * @LastEditTime: 2024-07-02 22:40:17 + * @LastEditTime: 2024-07-07 20:55:07 * @Email: [email protected] * @Describe: TODO */ -#ifndef _TEST_QUEUE_H_ -#define _TEST_QUEUE_H_ +#pragma once + #include "bbq.h" -#include "test_mix.h" #include <pthread.h> -#define TEST_DATA_MAGIC 0x1F // 为了兼容所有类型的数据,存储1字节大小的数据 +#include <pthread.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <time.h> + +#ifndef __cplusplus +// C +#include <stdatomic.h> +#endif -typedef void (*test_ring_free_f)(void *ring); -typedef int (*test_ring_enqueue_f)(void *ring, void *obj); -typedef int (*test_ring_dequeue_f)(void *ring, void *obj); -typedef uint32_t (*test_enqueue_burst_f)(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed); -typedef uint32_t (*test_dequeue_burst_f)(void *ring, void **obj_table, uint32_t n, uint32_t *wait_consumed); -typedef bool (*test_ring_empty_f)(void *ring); +enum ut_thread_type { + UT_THREAD_PRODUCER, + UT_THREAD_CONSUMER, + UT_THREAD_TYPE_MAX, +}; -typedef struct { +struct ut_metric { + struct timespec timestamp; // 系统时间戳 + // uint64_t cycles; // cpu运行的cycle +}; + +struct ut_report { + uint64_t throughput; // 吞吐量:每秒消耗的条目总数。 + double data_latency; // 数据延迟:每个数据在队列中停留的平均时间。 + double op_latency; // 操作延迟:每个入队或出队操作的平均延迟。 + double *fairness; // 公平性:每个生产者/消费者的吞吐量(占总吞吐的百分比) + double full_empty; // 队列满时入队的延迟/队列空时出队的延迟(仅用于简单工作负载)。 + uint64_t oversubscription; // 比核心/超线程更多的生产者和消费者的吞吐量 +}; + +enum ut_workload { + UT_WORKLOAD_SIMPLE, // 简单负载,每个生产者或消费者都有自己的线程,它们在循环中不断执行入队或出队操作。每次出队后都会验证数据。 + UT_WORKLOAD_COMPLEX, // 复杂负载,基于简单工作负载。生产者和消费者为数据分配空间,执行入队和出队,然后手动释放 + UT_WORKLOAD_MAX, +}; + +#define UT_RING_TYPE_BBQ_STR "bbq" +#define UT_RING_TYPE_DPDK_STR "dpdk" +#define UT_RING_TYPE_RMIND_STR "rmind" +enum ut_ring_type { + UT_RING_TYPE_BBQ, + UT_RING_TYPE_DPDK, + UT_RING_TYPE_RMIND, + UT_RING_TYPE_MAX, +}; + +struct ut_cfg_base { + char name[128]; // 配置文件名 + char introduce[128]; // 测试配置说明 + uint16_t cores_cnt; // 测试用核心个数 +}; + +struct ut_cfg_ring { + enum ut_ring_type ring_type; // ring buffer类型 + uint32_t producer_cnt; // 生产者个数 + uint32_t consumer_cnt; // 消费者个数 + enum ut_workload workload; // 负载模式 + uint64_t entries_cnt; // ring初始化时分配entry的个数 + uint32_t block_count; // bbq block个数,为0时表示根据entries_cnt自动计算 + uint32_t burst_cnt; // 批量出入队个数 +}; + +struct ut_cfg_run { + uint64_t run_ok_times; // 成功入队/入队次数 + uint64_t run_time; // 整体运行时间,单位秒 +}; + +struct ut_cfg { + struct ut_cfg_base base; + struct ut_cfg_ring ring; + struct ut_cfg_run run; +}; + +struct ut_ctl { + volatile bool running; // 默认为true,当设置为false,即所有生产者消费者即将退出 + pthread_barrier_t all_threads_start; +#ifndef __cplusplus + // C + atomic_uint producer_exit; +#else + // C++ 为了兼容gtest测试 + std::atomic<uint32_t> producer_exit; +#endif +}; + +struct ut_info_s { + struct ut_cfg cfg; + struct ut_ctl ctl; +}; + +enum ut_module { + UT_MODULE_UTEST, + UT_MODULE_COMMON, + UT_MODULE_DATA, + UT_MODULE_BCM, + UT_MODULE_TABLE, + UT_MODULE_RMIND, + UT_MODULE_MAX, +}; + +#ifdef UT_DEBUG +#define UT_DBG_LOG(fmt, ...) \ + do { \ + printf("[DBG][%s:%d:%s]" fmt "\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ + } while (0) + +#else +#define UT_DBG_LOG(fmt, ...) \ + do { \ + } while (0) +#endif + +#define UT_ERR_LOG(fmt, ...) \ + do { \ + printf("\x1b[31m [ERR][%s:%d:%s]" fmt "\x1b[0m\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ + } while (0) + +#define UT_INFO_LOG(fmt, ...) \ + do { \ + printf("[INFO][%s:%d:%s]" fmt "\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ + } while (0) + +#define UT_AVOID_WARNING(param) ((void)param) + +#define UT_PTR_ARRAY_DATA_INIT(table, t_type, t_count) \ + do { \ + if (table != NULL) { \ + memset(table, 0, sizeof(t_type *) * t_count); \ + for (uint32_t i = 0; i < t_count; i++) { \ + table[i] = (t_type *)ut_malloc(UT_MODULE_TABLE, sizeof(t_type)); \ + if (table[i] == NULL) { \ + for (uint32_t j = 0; j < i; j++) { \ + ut_free(UT_MODULE_TABLE, table[j]); \ + table[j] = NULL; \ + } \ + ut_free(UT_MODULE_TABLE, table); \ + break; \ + } \ + *table[i] = (t_type)UT_DATA_MAGIC; \ + } \ + } \ + } while (0) + +#define UT_PTR_ARRAY_DATA_DESTORY(table, t_count) \ + do { \ + if (table != NULL) { \ + for (uint32_t i = 0; i < t_count; i++) { \ + ut_free(UT_MODULE_TABLE, table[i]); \ + table[i] = NULL; \ + } \ + } \ + } while (0) + +#define UT_DOUBLE_PTR_DATA_INIT(table, t_type, t_count) \ + do { \ + table = (t_type **)ut_malloc(UT_MODULE_TABLE, sizeof(t_type *) * t_count); \ + if (table != NULL) { \ + UT_PTR_ARRAY_DATA_INIT(table, t_type, t_count); \ + } \ + } while (0) + +#define UT_DOUBLE_PTR_DATA_DESTORY(table, t_count) \ + do { \ + if (table != NULL) { \ + UT_PTR_ARRAY_DATA_DESTORY(table, t_count); \ + ut_free(UT_MODULE_TABLE, table); \ + table = NULL; \ + } \ + } while (0) + +#define UT_ARRAY_DATA_INIT(table, t_count) \ + do { \ + for (int i = 0; i < t_count; i++) { \ + table[i] = UT_DATA_MAGIC; \ + } \ + } while (0) + +#define UT_DATA_MAGIC 0x1F // 为了兼容所有类型的数据,存储1字节大小的数据 + +typedef void (*ut_ring_free_f)(void *ring); +typedef int (*ut_ring_enqueue_f)(void *ring, void *obj); +typedef int (*ut_ring_dequeue_f)(void *ring, void *obj); +typedef uint32_t (*ut_enqueue_burst_f)(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed); +typedef uint32_t (*ut_dequeue_burst_f)(void *ring, void **obj_table, uint32_t n, uint32_t *wait_consumed); +typedef bool (*ut_ring_empty_f)(void *ring); + +struct ut_queue { void *ring; - test_ring_type ring_type; - test_ring_free_f ring_free_f; - test_ring_enqueue_f enqueue_f; - test_ring_dequeue_f dequeue_f; - test_enqueue_burst_f enqueue_burst_f; - test_dequeue_burst_f dequeue_burst_f; -} test_queue_s; - -typedef struct { + enum ut_ring_type ring_type; + ut_ring_free_f ring_free_f; + ut_ring_enqueue_f enqueue_f; + ut_ring_dequeue_f dequeue_f; + ut_enqueue_burst_f enqueue_burst_f; + ut_dequeue_burst_f dequeue_burst_f; +}; + +struct ut_thread_arg { int core; uint16_t thread_idx; // 线程索引,不是pthread_id - test_thread_type_e ttype; - test_info_s *test_info; - test_queue_s *q; -} test_thread_arg_s; + enum ut_thread_type ttype; + struct ut_info_s *info; + struct ut_queue *q; +}; -typedef struct bcm_benchmark { +struct ut_data { uint64_t data; // 数据 - test_time_metric enqueue_time; // 入队时间 -} test_data; - -typedef struct { - test_data *data; - uint64_t data_cnt; -} test_complex_data; + struct ut_metric enqueue_time; // 入队时间 +}; -typedef struct { +struct ut_exit_data { pthread_t thread_id; - test_time_metric metric_start; - test_time_metric metric_end; uint64_t run_times; uint64_t ok_cnt; uint64_t latency_ns; // 仅消费者有效,数据停留的时延 uint64_t op_ok_latency_ns; // 成功操作的时延 uint64_t op_err_latency_ns; // 操作失败的时延, 如满队入队,空队出队 uint64_t data_error_cnt; // 发生过至少一次数据不一致的次数 - test_thread_arg_s *arg; size_t simple_data_cnt; - test_data **simple_data; -} test_exit_data; + struct ut_thread_arg *arg; + struct ut_metric metric_start; + struct ut_metric metric_end; + struct ut_data **simple_data; +}; -typedef struct { - test_time_metric use_time; +struct ut_merge_data { uint64_t run_times; uint64_t ok_cnt; uint64_t latency_ns; // 仅消费者有效,数据停留的时延 uint64_t op_ok_latency_ns; // 成功操作的时延 uint64_t op_err_latency_ns; // 操作失败的时延, 如满队入队,空队出队 uint64_t data_error_cnt; // 发生过至少一次数据不一致的次数 -} test_merge_data; - -typedef struct { - test_merge_data producer; - test_merge_data consumer; -} test_merge_s; - -enum test_data_type { - TEST_DATA_MAGIC_TYPE, - TEST_DATA_UINTPTR_TYPE, -}; - -extern void test_threads_destory(test_info_s *test_info, pthread_t *threads); -extern pthread_t *test_threads_create(test_info_s *test_info, test_queue_s *q); -extern void test_one_thread_create(test_info_s *test_info, test_queue_s *q, test_thread_type_e ttype, int core, uint16_t thread_id, pthread_t *thread); -extern void test_wait_all_threads_exit(test_info_s *test_info, uint32_t thread_cnt, pthread_t *threads, test_exit_data **exit_data); -extern void *test_thread_consumer_start(void *arg); -extern void *test_thread_producer_start(void *arg); -extern uint32_t test_exec_dequeue(test_queue_s *q, test_data **data, size_t burst_cnt, test_time_metric *op_use_diff); -extern uint32_t test_exec_enqueue(test_queue_s *q, test_data **data, size_t burst_cnt, test_time_metric *op_use_diff, uint16_t thread_idx); -extern void test_exit_data_destory(test_exit_data *data); -extern test_exit_data *test_exit_data_create(test_thread_arg_s *t_arg); -extern void test_wait_all_threads_ready(test_ctl *ctl); -extern void test_queue_destory(test_queue_s *q); -extern int test_queue_init_bbq(test_cfg *cfg, test_queue_s *q); -extern void test_merge_all_data(test_exit_data **exit_data, uint32_t thread_cnt, test_merge_s *merge); + struct ut_metric use_time; +}; + +struct ut_merge_s { + struct ut_merge_data producer; + struct ut_merge_data consumer; +}; + +enum ut_data_type { + UT_DATA_MAGIC_TYPE, + UT_DATA_UINTPTR_TYPE, +}; +extern struct ut_metric ut_clock_time_get(); +extern struct ut_metric ut_clock_time_sub(struct ut_metric now, struct ut_metric last); +extern int ut_load_config(const char *config, const char *ring_type, uint32_t burst_cnt, struct ut_cfg *cfg); +extern enum ut_workload ut_workload_str2enum(const char *workload); +extern enum ut_ring_type ut_ring_type_str2enum(const char *ring_type); +extern bool ut_clock_time_is_zero(struct ut_metric *metric); +extern bool ut_timespec_is_after(const struct timespec *a, const struct timespec *b); +extern char *ut_ring_type_enum2str(enum ut_ring_type ring_type); +extern uint64_t ut_clock_time_to_ns(struct ut_metric *metric); +extern double ut_clock_time_to_double(struct ut_metric *metric); +extern void *ut_malloc(enum ut_module module, size_t size); +extern void ut_free(enum ut_module module, void *ptr); +extern void ut_memory_counter_print(); +extern void ut_memory_counter_clear(); +extern bool ut_malloc_free_equal(); +extern int ut_setaffinity(int core_id); +extern void *ut_malloc_def_callback(int32_t socket_id __attribute__((unused)), size_t size); +extern void ut_free_def_callback(void *ptr, size_t size __attribute__((unused))); +extern void ut_threads_destory(struct ut_info_s *info, pthread_t *threads); +extern pthread_t *ut_threads_create(struct ut_info_s *info, struct ut_queue *q); +extern void ut_one_thread_create(struct ut_info_s *info, struct ut_queue *q, enum ut_thread_type ttype, int core, uint16_t thread_id, pthread_t *thread); +extern void ut_wait_all_threads_exit(struct ut_info_s *info, uint32_t thread_cnt, pthread_t *threads, struct ut_exit_data **exit_data); +extern void *ut_thread_consumer_start(void *arg); +extern void *ut_thread_producer_start(void *arg); +extern uint32_t ut_exec_dequeue(struct ut_queue *q, struct ut_data **data, size_t burst_cnt, struct ut_metric *op_use_diff); +extern uint32_t ut_exec_enqueue(struct ut_queue *q, struct ut_data **data, size_t burst_cnt, struct ut_metric *op_use_diff, uint16_t thread_idx); +extern void ut_exit_data_destory(struct ut_exit_data *data); +extern struct ut_exit_data *ut_exit_data_create(struct ut_thread_arg *t_arg); +extern void ut_wait_all_threads_ready(struct ut_ctl *ctl); +extern void ut_queue_destory(struct ut_queue *q); +extern int ut_queue_init_bbq(struct ut_cfg *cfg, struct ut_queue *q); +extern void ut_merge_all_data(struct ut_exit_data **exit_data, uint32_t thread_cnt, struct ut_merge_s *merge); extern uint64_t bbq_head_idx(struct bbq *q, uint64_t x); extern uint64_t bbq_cur_off(struct bbq *q, uint64_t x); extern uint64_t bbq_head_vsn(struct bbq *q, uint64_t x); extern uint64_t bbq_cur_vsn(struct bbq *q, uint64_t x); -extern test_data **test_data_create(size_t cnt, enum test_data_type); -extern void test_data_destory(test_data **data, size_t cnt); -#endif
\ No newline at end of file +extern struct ut_data **ut_data_create(size_t cnt, enum ut_data_type); +extern void ut_data_destory(struct ut_data **data, size_t cnt);
\ No newline at end of file diff --git a/bbq/tests/unittest/ut.h b/bbq/tests/unittest/ut.h index a6ef9ad..32e1a2c 100644 --- a/bbq/tests/unittest/ut.h +++ b/bbq/tests/unittest/ut.h @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-14 15:56:17 + * @LastEditTime: 2024-07-07 18:07:51 * @Email: [email protected] * @Describe: TODO */ @@ -8,7 +8,7 @@ #ifndef _UT_H_ #define _UT_H_ #include "bbq.h" -#include "test_mix.h" +#include "test_queue.h" #include <stdint.h> typedef struct { @@ -25,13 +25,13 @@ typedef struct { typedef struct { pthread_t thread_id; - test_thread_type_e type; // 线程类型 - uint64_t exec_times; // 执行次数 - uint64_t succ_times; // 成功次数 - uint64_t full_times; // 失败,队列满次数 - uint64_t busy_times; // 失败,队列忙次数 - uint64_t empty_times; // 失败,队列空次数 - testdata_s *data; // 线程数据 - thread_arg_s *arg; // 创建线程时传入的参数 + enum ut_thread_type type; // 线程类型 + uint64_t exec_times; // 执行次数 + uint64_t succ_times; // 成功次数 + uint64_t full_times; // 失败,队列满次数 + uint64_t busy_times; // 失败,队列忙次数 + uint64_t empty_times; // 失败,队列空次数 + testdata_s *data; // 线程数据 + thread_arg_s *arg; // 创建线程时传入的参数 } thread_data_s; #endif
\ No newline at end of file diff --git a/bbq/tests/unittest/ut_example.cc b/bbq/tests/unittest/ut_example.cc index 464702c..0dc12ce 100644 --- a/bbq/tests/unittest/ut_example.cc +++ b/bbq/tests/unittest/ut_example.cc @@ -1,18 +1,30 @@ /* * @Author: liuyu - * @LastEditTime: 2024-07-07 17:39:47 + * @LastEditTime: 2024-07-07 20:55:43 * @Email: [email protected] * @Describe: 简单的测试用例,测试基本功能 */ #include "gtest/gtest.h" extern "C" { -#include "test_mix.h" #include "test_queue.h" #include "ut.h" +#include <math.h> extern bool bbq_debug_check_array_bounds(struct bbq *q); extern void bbq_struct_print(struct bbq *q); extern uint32_t bbq_enqueue_burst_elem_2d_array(struct bbq *q, void *const *obj_table, uint32_t n, uint32_t *wait_consumed); +extern bool bbq_check_power_of_two(int n); +extern unsigned bbq_ceil_log2(uint64_t x); +extern uint64_t bbq_fetch_max(union bbq_atomic64 *atomic, uint64_t upd, bool single); +extern bool ut_malloc_free_equal(); +extern int bbq_bnbs_calc(uint32_t entries, uint32_t *bn, uint32_t *bs); +extern void bbq_atomic64_store(union bbq_atomic64 *atomic, uint64_t value, bool single); +extern uint64_t bbq_atomic64_load(union bbq_atomic64 *atomic, bool single); +extern bool bbq_debug_check_array_bounds(struct bbq *q); +extern struct bbq *bbq_create_elem_with_bnbs(const char *name, uint32_t bn, uint32_t bs, + size_t obj_size, int socket_id, uint32_t flags, + bbq_malloc_f malloc_f, bbq_free_f free_f); +extern uint64_t bbq_atomic64_load(union bbq_atomic64 *atomic, bool single); } #define BUF_CNT 4096 @@ -21,21 +33,21 @@ class bbq_example : public testing::Test { protected: virtual void SetUp() override { // 1.清空内存malloc/free统计 - test_memory_counter_clear(); + ut_memory_counter_clear(); // 2.入队空间初始化 - TEST_DOUBLE_PTR_DATA_INIT(enq_table1, uint16_t, BUF_CNT); - TEST_PTR_ARRAY_DATA_INIT(enq_table2, uint16_t, BUF_CNT); - TEST_ARRAY_DATA_INIT(enq_table3, BUF_CNT); + UT_DOUBLE_PTR_DATA_INIT(enq_table1, uint16_t, BUF_CNT); + UT_PTR_ARRAY_DATA_INIT(enq_table2, uint16_t, BUF_CNT); + UT_ARRAY_DATA_INIT(enq_table3, BUF_CNT); } virtual void TearDown() override { // 1.释放测试数据 - TEST_DOUBLE_PTR_DATA_DESTORY(enq_table1, BUF_CNT); - TEST_PTR_ARRAY_DATA_DESTORY(enq_table2, BUF_CNT); + UT_DOUBLE_PTR_DATA_DESTORY(enq_table1, BUF_CNT); + UT_PTR_ARRAY_DATA_DESTORY(enq_table2, BUF_CNT); // 2.内存泄漏检测 - EXPECT_TRUE(test_malloc_free_equal()); + EXPECT_TRUE(ut_malloc_free_equal()); } // 入队数据 @@ -50,8 +62,8 @@ TEST_F(bbq_example, single_retry_new_cp_ptr) { uint16_t *deq_data = NULL; // 创建队列 - struct bbq *q = bbq_create("test_bbq", BUF_CNT, BBQ_SOCKET_ID_ANY, - BBQ_F_RETRY_NEW, test_malloc_def_callback, test_free_def_callback); + struct bbq *q = bbq_create("ut_bbq", BUF_CNT, BBQ_SOCKET_ID_ANY, + BBQ_F_RETRY_NEW, ut_malloc_def_callback, ut_free_def_callback); ASSERT_NE(q, nullptr); // 空队出队失败 @@ -78,7 +90,7 @@ TEST_F(bbq_example, single_retry_new_cp_ptr) { for (uint32_t i = 0; i < BUF_CNT; i++) { ret = bbq_dequeue(q, (void **)&deq_data); if (ret == 0) { - EXPECT_EQ(*deq_data, TEST_DATA_MAGIC); + EXPECT_EQ(*deq_data, UT_DATA_MAGIC); cnt++; } } @@ -96,9 +108,9 @@ TEST_F(bbq_example, single_retry_new_cp_value) { uint16_t deq_data; // 创建队列 - struct bbq *q = bbq_create_elem("test_bbq", BUF_CNT, sizeof(uint16_t), + struct bbq *q = bbq_create_elem("ut_bbq", BUF_CNT, sizeof(uint16_t), BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, - test_malloc_def_callback, test_free_def_callback); + ut_malloc_def_callback, ut_free_def_callback); ASSERT_NE(q, nullptr); // 空队出队失败 @@ -125,7 +137,7 @@ TEST_F(bbq_example, single_retry_new_cp_value) { for (uint32_t i = 0; i < BUF_CNT; i++) { ret = bbq_dequeue_elem(q, &deq_data); if (ret == 0) { - EXPECT_EQ(deq_data, TEST_DATA_MAGIC); + EXPECT_EQ(deq_data, UT_DATA_MAGIC); cnt++; } } @@ -145,9 +157,9 @@ TEST_F(bbq_example, single_drop_old_cp_pointer) { uint64_t second_cnt = 1000; // 创建队列 - struct bbq *q = bbq_create("test_bbq", BUF_CNT, BBQ_SOCKET_ID_ANY, - BBQ_F_DROP_OLD, test_malloc_def_callback, - test_free_def_callback); + struct bbq *q = bbq_create("ut_bbq", BUF_CNT, BBQ_SOCKET_ID_ANY, + BBQ_F_DROP_OLD, ut_malloc_def_callback, + ut_free_def_callback); ASSERT_NE(q, nullptr); EXPECT_LT(second_cnt, q->bs * q->bn); @@ -179,7 +191,7 @@ TEST_F(bbq_example, single_drop_old_cp_pointer) { for (uint32_t i = 0; i < BUF_CNT; i++) { ret = bbq_dequeue(q, (void **)&deq_data); if (ret == 0) { - EXPECT_EQ(*deq_data, TEST_DATA_MAGIC); + EXPECT_EQ(*deq_data, UT_DATA_MAGIC); cnt++; } } @@ -201,9 +213,9 @@ TEST_F(bbq_example, single_drop_old_cp_value) { uint64_t second_cnt = 1000; // 创建队列 - struct bbq *q = bbq_create_elem("test_bbq", BUF_CNT, sizeof(uint16_t), + struct bbq *q = bbq_create_elem("ut_bbq", BUF_CNT, sizeof(uint16_t), BBQ_SOCKET_ID_ANY, BBQ_F_DROP_OLD, - test_malloc_def_callback, test_free_def_callback); + ut_malloc_def_callback, ut_free_def_callback); ASSERT_NE(q, nullptr); EXPECT_LT(second_cnt, q->bs * q->bn); @@ -235,7 +247,7 @@ TEST_F(bbq_example, single_drop_old_cp_value) { for (uint32_t i = 0; i < BUF_CNT; i++) { ret = bbq_dequeue_elem(q, &deq_data); if (ret == 0) { - EXPECT_EQ(deq_data, TEST_DATA_MAGIC); + EXPECT_EQ(deq_data, UT_DATA_MAGIC); cnt++; } } @@ -255,13 +267,13 @@ TEST_F(bbq_example, burst_retry_new_cp_value) { uint64_t first_cnt = 4000; uint64_t second_cnt = 1000; uint16_t deq_table1[BUF_CNT] = {0}; - uint16_t *deq_table2 = (uint16_t *)test_malloc(TEST_MODULE_DATA, sizeof(uint16_t) * BUF_CNT); + uint16_t *deq_table2 = (uint16_t *)ut_malloc(UT_MODULE_DATA, sizeof(uint16_t) * BUF_CNT); uint32_t wait_consumed = 0; // 创建队列 - q = bbq_create_elem("test_bbq", BUF_CNT, sizeof(uint16_t), + q = bbq_create_elem("ut_bbq", BUF_CNT, sizeof(uint16_t), BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW | BBQ_F_ENABLE_STAT, - test_malloc_def_callback, test_free_def_callback); + ut_malloc_def_callback, ut_free_def_callback); ASSERT_NE(q, nullptr); EXPECT_LT(first_cnt, q->bn * q->bs); @@ -288,15 +300,15 @@ TEST_F(bbq_example, burst_retry_new_cp_value) { // 验证数据 for (uint32_t i = 0; i < ret1; i++) { - EXPECT_EQ(deq_table1[i], TEST_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(deq_table1[i], UT_DATA_MAGIC) << "i :" << i; } for (uint32_t i = 0; i < ret2; i++) { - EXPECT_EQ(deq_table2[i], TEST_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(deq_table2[i], UT_DATA_MAGIC) << "i :" << i; } EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - test_free(TEST_MODULE_DATA, deq_table2); + ut_free(UT_MODULE_DATA, deq_table2); bbq_destory(q); } @@ -308,12 +320,12 @@ TEST_F(bbq_example, burst_retry_new_cp_pointer) { uint64_t second_cnt = 1000; uint32_t wait_consumed = 0; uint16_t *deq_table1[BUF_CNT] = {0}; - uint16_t **deq_table2 = (uint16_t **)test_malloc(TEST_MODULE_DATA, sizeof(uint16_t *) * BUF_CNT); + uint16_t **deq_table2 = (uint16_t **)ut_malloc(UT_MODULE_DATA, sizeof(uint16_t *) * BUF_CNT); // 创建队列 - q = bbq_create("test_bbq", BUF_CNT, BBQ_SOCKET_ID_ANY, + q = bbq_create("ut_bbq", BUF_CNT, BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW | BBQ_F_ENABLE_STAT, - test_malloc_def_callback, test_free_def_callback); + ut_malloc_def_callback, ut_free_def_callback); ASSERT_NE(q, nullptr); EXPECT_LT(first_cnt, q->bn * q->bs); @@ -339,15 +351,15 @@ TEST_F(bbq_example, burst_retry_new_cp_pointer) { // 验证数据 for (uint32_t i = 0; i < ret1; i++) { - EXPECT_EQ(*deq_table1[i], TEST_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(*deq_table1[i], UT_DATA_MAGIC) << "i :" << i; } for (uint32_t i = 0; i < ret2; i++) { - EXPECT_EQ(*deq_table2[i], TEST_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(*deq_table2[i], UT_DATA_MAGIC) << "i :" << i; } EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - test_free(TEST_MODULE_DATA, deq_table2); + ut_free(UT_MODULE_DATA, deq_table2); bbq_destory(q); } @@ -359,11 +371,11 @@ TEST_F(bbq_example, burst_drop_old_cp_pointer) { uint64_t second_cnt = 1000; uint32_t wait_consumed = 0; uint16_t *deq_table1[BUF_CNT] = {0}; - uint16_t **deq_table2 = (uint16_t **)test_malloc(TEST_MODULE_DATA, sizeof(uint16_t *) * BUF_CNT); + uint16_t **deq_table2 = (uint16_t **)ut_malloc(UT_MODULE_DATA, sizeof(uint16_t *) * BUF_CNT); // 创建队列 - q = bbq_create("test_bbq", BUF_CNT, BBQ_SOCKET_ID_ANY, BBQ_F_DROP_OLD, - test_malloc_def_callback, test_free_def_callback); + q = bbq_create("ut_bbq", BUF_CNT, BBQ_SOCKET_ID_ANY, BBQ_F_DROP_OLD, + ut_malloc_def_callback, ut_free_def_callback); ASSERT_NE(q, nullptr); EXPECT_GT(second_cnt, q->bs); EXPECT_LT(second_cnt, q->bs * q->bn); @@ -386,7 +398,7 @@ TEST_F(bbq_example, burst_drop_old_cp_pointer) { // 验证数据 for (uint32_t i = 0; i < ret1; i++) { - EXPECT_EQ(*deq_table1[i], TEST_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(*deq_table1[i], UT_DATA_MAGIC) << "i :" << i; } // 此时生产者和消费者在同一块上,入队个数为队列容量的N倍,由于发生了覆盖,且依旧在同一块上,数据全作废 @@ -398,7 +410,7 @@ TEST_F(bbq_example, burst_drop_old_cp_pointer) { } EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - test_free(TEST_MODULE_DATA, deq_table2); + ut_free(UT_MODULE_DATA, deq_table2); bbq_destory(q); } @@ -412,9 +424,9 @@ TEST_F(bbq_example, burst_drop_old_cp_value) { uint16_t deq_table1[BUF_CNT] = {0}; // 创建队列 - q = bbq_create_elem("test_bbq", BUF_CNT, sizeof(uint16_t), + q = bbq_create_elem("ut_bbq", BUF_CNT, sizeof(uint16_t), BBQ_SOCKET_ID_ANY, BBQ_F_DROP_OLD, - test_malloc_def_callback, test_free_def_callback); + ut_malloc_def_callback, ut_free_def_callback); ASSERT_NE(q, nullptr); EXPECT_GT(second_cnt, q->bs); EXPECT_LT(second_cnt, q->bs * q->bn); @@ -438,7 +450,737 @@ TEST_F(bbq_example, burst_drop_old_cp_value) { // 验证数据 for (uint32_t i = 0; i < ret1; i++) { - EXPECT_EQ(deq_table1[i], TEST_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(deq_table1[i], UT_DATA_MAGIC) << "i :" << i; + } + + EXPECT_TRUE(bbq_debug_check_array_bounds(q)); + bbq_destory(q); +} + +typedef struct { + uint64_t thread_cnt; + bbq_atomic64 data; + aotmic_uint64 ready_thread_cnt; +} ut_fetch_arg; + +void *fetch_max_thread_func(void *arg) { + ut_fetch_arg *fetch_arg = (ut_fetch_arg *)arg; + fetch_arg->ready_thread_cnt.fetch_add(1); + + while (fetch_arg->ready_thread_cnt.load() != fetch_arg->thread_cnt) { + } + + uint64_t *ret = (uint64_t *)ut_malloc(UT_MODULE_UTEST, sizeof(*ret)); + // 不同线程写入不同的>3的数 + *ret = bbq_fetch_max(&fetch_arg->data, pthread_self() + 3, false); + pthread_exit(ret); +} + +TEST_F(bbq_example, mpmc) { + struct ut_info_s info { + .cfg = { + .base = { + .name = {}, + .introduce = {}, + .cores_cnt = 4, + }, + .ring = { + .ring_type = UT_RING_TYPE_BBQ, + .producer_cnt = 4, + .consumer_cnt = 4, + .workload = UT_WORKLOAD_SIMPLE, + .entries_cnt = 4096, + .block_count = 0, + .burst_cnt = 4, + }, + .run = { + .run_ok_times = 9000000, + .run_time = 0, + }, + }, + .ctl = { + .running = true, + .all_threads_start = {}, + .producer_exit = {}, + }, + }; + + // 队列初始化 + int ret = -1; + struct ut_queue q; + ret = ut_queue_init_bbq(&info.cfg, &q); + ASSERT_TRUE(ret == 0); + + // 创建线程 + pthread_t *threads = ut_threads_create(&info, &q); + ASSERT_TRUE(threads); + + // 等待所有线程完成,回收数据 + uint32_t thread_cnt = info.cfg.ring.producer_cnt + info.cfg.ring.consumer_cnt; + struct ut_exit_data **exit_data = (struct ut_exit_data **)ut_malloc(UT_MODULE_UTEST, sizeof(struct ut_exit_data **) * (thread_cnt)); + ut_wait_all_threads_exit(&info, thread_cnt, threads, exit_data); + + // 比较数据 + struct ut_merge_s merge; + memset(&merge, 0, sizeof(merge)); + ut_merge_all_data(exit_data, thread_cnt, &merge); + EXPECT_EQ(merge.consumer.data_error_cnt, 0); + EXPECT_EQ(merge.consumer.ok_cnt, merge.producer.ok_cnt); + + // 释放数据 + for (uint32_t i = 0; i < thread_cnt; i++) { + ut_exit_data_destory(exit_data[i]); + } + ut_free(UT_MODULE_UTEST, exit_data); + ut_threads_destory(&info, threads); + EXPECT_TRUE(bbq_debug_check_array_bounds((struct bbq *)q.ring)); + ut_queue_destory(&q); +} + +TEST_F(bbq_example, bbq_fetch_max) { + uint64_t ret = 0; + ut_fetch_arg arg; + + bool single = false; + arg.data.m.store(0); + arg.thread_cnt = 0; + arg.ready_thread_cnt.store(0); + + bbq_atomic64_store(&arg.data, 1, single); // 初始化1 + arg.thread_cnt = 50; + + ret = bbq_fetch_max(&arg.data, 2, single); // max比较后设置为2 + EXPECT_EQ(bbq_atomic64_load(&arg.data, single), 2); + EXPECT_EQ(ret, 1); + + pthread_t *threads = (pthread_t *)ut_malloc(UT_MODULE_UTEST, sizeof(*threads) * arg.thread_cnt); + for (uint64_t i = 0; i < arg.thread_cnt; i++) { + // 多个线程同时fetch_max,输入 > 3的数据 + pthread_create(&threads[i], NULL, fetch_max_thread_func, (void *)&arg); + } + + int eq_cnt = 0; + for (uint64_t i = 0; i < arg.thread_cnt; i++) { + uint64_t *tret; + pthread_join(threads[i], (void **)&tret); // 等待每个线程结束 + if (*tret == 2) { + eq_cnt++; // 统计返回2的个数 + } + ut_free(UT_MODULE_UTEST, tret); + } + + // EXPECT_EQ(eq_cnt, 1); + ut_free(UT_MODULE_UTEST, threads); +} + +TEST_F(bbq_example, power_of_two) { + uint32_t tmp = 0; + uint32_t max = pow(2, 32) - 1; + + EXPECT_FALSE(bbq_check_power_of_two(0)); + + tmp = 3; + for (uint32_t val = 5; val < max; val *= tmp) { + EXPECT_FALSE(bbq_check_power_of_two(val)); + if (val >= max / tmp) { + break; // 即将越界 + } + } + + tmp = 2; + for (uint32_t val = 1; val < max; val *= tmp) { + EXPECT_TRUE(bbq_check_power_of_two(val)); + if (val >= max / tmp) { + break; + } + } +} + +TEST_F(bbq_example, bbq_block_number_calc) { + uint32_t tmp = 2; + uint32_t max = pow(2, 32) - 1; + uint32_t bn = 0, bs = 0; + int ret = 0; + + ret = bbq_bnbs_calc(1, &bn, &bs); + EXPECT_EQ(ret, BBQ_ERR_OUT_OF_RANGE); + + for (uint32_t val = 2; val < max; val *= tmp) { + ret = bbq_bnbs_calc(val, &bn, &bs); + EXPECT_EQ(ret, BBQ_OK); + if (val <= 128) { + EXPECT_EQ(bn, 2); + } else if (val <= 2048) { + EXPECT_EQ(bn, 4); + } else if (val <= 32768) { + EXPECT_EQ(bn, 8); + } else if (val <= 524288) { + EXPECT_EQ(bn, 16); + } else if (val <= 8388608) { + EXPECT_EQ(bn, 32); + } else if (val <= 134217728) { + EXPECT_EQ(bn, 64); + } else if (val <= 2147483648) { + EXPECT_EQ(bn, 128); + } else { + EXPECT_TRUE(0); // 异常 + } + + if (val >= max / tmp) { + break; + } + } +} + +#define OFFSETOF(type, member) ((size_t) & ((type *)0)->member) +#define PRINT_OFFSETOF(type, member) printf("Offset of '%s' in '%s' is %zu\n", #member, #type, OFFSETOF(type, member)) +#define PTR_ALIGNED_64(ptr) (((uintptr_t)ptr & (64 - 1)) == 0) +#define SIZE_ALIGNED_64(v) (((sizeof(v)) & (64 - 1)) == 0) + +TEST_F(bbq_example, bbq_cache_line) { + + // 创建队列 + struct bbq *q = bbq_create("ut_bbq", 4096, BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, + ut_malloc_def_callback, ut_free_def_callback); + ASSERT_NE(q, nullptr); + + // 首地址64字节对齐 + EXPECT_EQ(PTR_ALIGNED_64(q), true); + + // 关键成员64字节对齐 + EXPECT_EQ(PTR_ALIGNED_64(&q->name), true); + EXPECT_EQ(PTR_ALIGNED_64(&q->socket_id), true); + EXPECT_EQ(PTR_ALIGNED_64(&q->phead.value), true); + EXPECT_EQ(PTR_ALIGNED_64(&q->chead.value), true); + EXPECT_EQ(PTR_ALIGNED_64(&q->blocks), true); + EXPECT_EQ(PTR_ALIGNED_64(&q->blocks[0].committed), true); + EXPECT_EQ(PTR_ALIGNED_64(&q->blocks[0].entries), true); + + EXPECT_EQ(SIZE_ALIGNED_64(struct bbq_head), true); + EXPECT_EQ(SIZE_ALIGNED_64(struct bbq_block), true); + + // PRINT_OFFSETOF(struct bbq, name); + // PRINT_OFFSETOF(struct bbq, socket_id); + // PRINT_OFFSETOF(struct bbq, phead); + // PRINT_OFFSETOF(struct bbq, chead); + // PRINT_OFFSETOF(struct bbq, blocks); + + bbq_destory(q); +} + +void expect_phead(struct bbq *q, uint64_t idx, uint64_t vsn, int line) { + uint64_t ph = bbq_atomic64_load(&q->phead.value, q->prod_single); + EXPECT_EQ(bbq_head_idx(q, ph), idx) << "line: " << line; + EXPECT_EQ(bbq_head_vsn(q, ph), vsn) << "line: " << line; +} + +void expect_chead(struct bbq *q, uint64_t idx, uint64_t vsn, int line) { + uint64_t ch = bbq_atomic64_load(&q->chead.value, q->cons_single); + EXPECT_EQ(bbq_head_idx(q, ch), idx) << "line: " << line; + EXPECT_EQ(bbq_head_vsn(q, ch), vsn) << "line: " << line; +} + +void expect_eq_allocated(struct bbq *q, bbq_block *block, uint64_t off, uint64_t vsn, int line) { + uint64_t allocated = bbq_atomic64_load(&block->allocated, q->prod_single); + EXPECT_EQ(bbq_cur_off(q, allocated), off) << "line: " << line; + EXPECT_EQ(bbq_cur_vsn(q, allocated), vsn) << "line: " << line; +} + +void expect_eq_committed(struct bbq *q, bbq_block *block, uint64_t off, uint64_t vsn, int line) { + uint64_t committed = bbq_atomic64_load(&block->committed, q->prod_single); + EXPECT_EQ(bbq_cur_off(q, committed), off) << "line: " << line; + EXPECT_EQ(bbq_cur_vsn(q, committed), vsn) << "line: " << line; +} + +void expect_eq_consumed(struct bbq *q, bbq_block *block, uint64_t off, uint64_t vsn, int line) { + uint64_t consumed = bbq_atomic64_load(&block->consumed, q->cons_single); + EXPECT_EQ(bbq_cur_off(q, consumed), off) << "line: " << line; + EXPECT_EQ(bbq_cur_vsn(q, consumed), vsn) << "line: " << line; +} + +void expect_eq_reserved(struct bbq *q, bbq_block *block, uint64_t off, uint64_t vsn, int line) { + uint64_t reserved = bbq_atomic64_load(&block->reserved, q->cons_single); + EXPECT_EQ(bbq_cur_off(q, reserved), off) << "line: " << line; + EXPECT_EQ(bbq_cur_vsn(q, reserved), vsn) << "line: " << line; +} + +// 初始化状态 +TEST_F(bbq_example, head_cursor_init) { + struct bbq *q; + uint32_t bn = 2; + uint32_t bs = 4; + q = bbq_create_elem_with_bnbs("ut_bbq", bn, bs, sizeof(int), + BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, + ut_malloc_def_callback, ut_free_def_callback); + ASSERT_NE(q, nullptr); + + // 1.初始化状态,除了第一个block外其他块的4个游标都指向最后一个条目 + + EXPECT_EQ(bbq_atomic64_load(&q->phead.value, q->prod_single), 0); + EXPECT_EQ(bbq_atomic64_load(&q->chead.value, q->cons_single), 0); + + expect_eq_allocated(q, &q->blocks[0], 0, 0, __LINE__); + expect_eq_committed(q, &q->blocks[0], 0, 0, __LINE__); + expect_eq_reserved(q, &q->blocks[0], 0, 0, __LINE__); + expect_eq_consumed(q, &q->blocks[0], 0, 0, __LINE__); + for (uint32_t i = 1; i < bn; i++) { + expect_eq_allocated(q, &q->blocks[i], bs, 0, __LINE__); + expect_eq_committed(q, &q->blocks[i], bs, 0, __LINE__); + expect_eq_reserved(q, &q->blocks[i], bs, 0, __LINE__); + expect_eq_consumed(q, &q->blocks[i], bs, 0, __LINE__); + } + EXPECT_TRUE(bbq_debug_check_array_bounds(q)); + bbq_destory(q); +} + +void ut_produce_something(uint32_t produce_cnt) { + int ret = 0; + struct bbq *q; + uint32_t bn = 8; + uint32_t bs = 4096; + int enqueue_data = UT_DATA_MAGIC; + int dequeue_data = 0; + + EXPECT_GT(produce_cnt, 0); + EXPECT_LE(produce_cnt, bs); + + q = bbq_create_elem_with_bnbs("ut_bbq", bn, bs, sizeof(int), + BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, + ut_malloc_def_callback, ut_free_def_callback); + ASSERT_NE(q, nullptr); + + // 生产produce_cnt + for (uint32_t i = 0; i < produce_cnt; i++) { + ret = bbq_enqueue_elem(q, &enqueue_data); + EXPECT_TRUE(ret == BBQ_OK); + } + + EXPECT_EQ(bbq_atomic64_load(&q->phead.value, q->prod_single), 0); + EXPECT_EQ(bbq_atomic64_load(&q->chead.value, q->cons_single), 0); + expect_eq_allocated(q, &q->blocks[0], produce_cnt, 0, __LINE__); + expect_eq_committed(q, &q->blocks[0], produce_cnt, 0, __LINE__); + expect_eq_reserved(q, &q->blocks[0], 0, 0, __LINE__); + expect_eq_consumed(q, &q->blocks[0], 0, 0, __LINE__); + + // 消费完 + for (uint32_t i = 0; i < produce_cnt; i++) { + ret = bbq_dequeue_elem(q, &dequeue_data); + EXPECT_TRUE(ret == BBQ_OK); + EXPECT_EQ(dequeue_data, UT_DATA_MAGIC); + } + + EXPECT_EQ(bbq_atomic64_load(&q->phead.value, q->prod_single), 0); + EXPECT_EQ(bbq_atomic64_load(&q->chead.value, q->cons_single), 0); + expect_eq_allocated(q, &q->blocks[0], produce_cnt, 0, __LINE__); + expect_eq_committed(q, &q->blocks[0], produce_cnt, 0, __LINE__); + expect_eq_reserved(q, &q->blocks[0], produce_cnt, 0, __LINE__); + expect_eq_consumed(q, &q->blocks[0], produce_cnt, 0, __LINE__); + + for (uint32_t i = 1; i < bn; i++) { + expect_eq_allocated(q, &q->blocks[i], bs, 0, __LINE__); + expect_eq_committed(q, &q->blocks[i], bs, 0, __LINE__); + expect_eq_reserved(q, &q->blocks[i], bs, 0, __LINE__); + expect_eq_consumed(q, &q->blocks[i], bs, 0, __LINE__); + } + EXPECT_TRUE(bbq_debug_check_array_bounds(q)); + bbq_destory(q); +} +// 在第一块内生产,然后被消费完 +TEST_F(bbq_example, head_cursor_produce_something) { + ut_produce_something(1); + ut_produce_something(567); + ut_produce_something(789); + ut_produce_something(4096); +} + +void ut_produce_next_block(uint32_t over) { + int ret = 0; + struct bbq *q; + uint32_t bn = 8; + uint32_t bs = 4096; + uint32_t produce_cnt = bs + over; + int enqueue_data = UT_DATA_MAGIC; + int dequeue_data = 0; + + EXPECT_GT(over, 0); + EXPECT_LT(over, bs); + + q = bbq_create_elem_with_bnbs("ut_bbq", bn, bs, sizeof(int), + BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, + ut_malloc_def_callback, ut_free_def_callback); + ASSERT_NE(q, nullptr); + + // 生产至第二块的第一个entry + for (uint32_t i = 0; i < produce_cnt; i++) { + ret = bbq_enqueue_elem(q, &enqueue_data); + EXPECT_TRUE(ret == BBQ_OK); + } + + EXPECT_EQ(bbq_atomic64_load(&q->chead.value, q->cons_single), 0); + expect_phead(q, 1, 0, __LINE__); + expect_eq_allocated(q, &q->blocks[0], bs, 0, __LINE__); + expect_eq_committed(q, &q->blocks[0], bs, 0, __LINE__); + expect_eq_reserved(q, &q->blocks[0], 0, 0, __LINE__); + expect_eq_consumed(q, &q->blocks[0], 0, 0, __LINE__); + + expect_eq_allocated(q, &q->blocks[1], over, 1, __LINE__); + expect_eq_committed(q, &q->blocks[1], over, 1, __LINE__); + expect_eq_reserved(q, &q->blocks[1], bs, 0, __LINE__); + expect_eq_consumed(q, &q->blocks[1], bs, 0, __LINE__); + + // 消费完 + for (uint32_t i = 0; i < produce_cnt; i++) { + ret = bbq_dequeue_elem(q, &dequeue_data); + EXPECT_TRUE(ret == BBQ_OK); + EXPECT_EQ(dequeue_data, UT_DATA_MAGIC); + } + + expect_phead(q, 1, 0, __LINE__); + expect_chead(q, 1, 0, __LINE__); + expect_eq_allocated(q, &q->blocks[0], bs, 0, __LINE__); + expect_eq_committed(q, &q->blocks[0], bs, 0, __LINE__); + expect_eq_reserved(q, &q->blocks[0], bs, 0, __LINE__); + expect_eq_consumed(q, &q->blocks[0], bs, 0, __LINE__); + + expect_eq_allocated(q, &q->blocks[1], over, 1, __LINE__); + expect_eq_committed(q, &q->blocks[1], over, 1, __LINE__); + expect_eq_reserved(q, &q->blocks[1], over, 1, __LINE__); + expect_eq_consumed(q, &q->blocks[1], over, 1, __LINE__); + + EXPECT_TRUE(bbq_debug_check_array_bounds(q)); + bbq_destory(q); +} + +// 第一块生产完毕,第二块生产了若干,然后被消费完 +TEST_F(bbq_example, head_cursor_produce_next_block) { + ut_produce_next_block(1); + ut_produce_next_block(123); + ut_produce_next_block(456); + ut_produce_next_block(4095); +} + +void ut_produce_all_loop(uint32_t loop) { + int ret = 0; + struct bbq *q; + uint32_t bn = 8; + uint32_t bs = 4096; + uint32_t produce_cnt = bn * bs; + int enqueue_data = UT_DATA_MAGIC; + int dequeue_data = 0; + + q = bbq_create_elem_with_bnbs("ut_bbq", bn, bs, sizeof(int), + BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, + ut_malloc_def_callback, ut_free_def_callback); + ASSERT_NE(q, nullptr); + + for (uint32_t cnt = 0; cnt < loop; cnt++) { + // 所有entry生产完毕 + for (uint32_t i = 0; i < produce_cnt; i++) { + ret = bbq_enqueue_elem(q, &enqueue_data); + EXPECT_TRUE(ret == BBQ_OK); + } + + // 消费完 + for (uint32_t i = 0; i < produce_cnt; i++) { + ret = bbq_dequeue_elem(q, &dequeue_data); + EXPECT_TRUE(ret == BBQ_OK); + EXPECT_EQ(dequeue_data, UT_DATA_MAGIC); + } + } + + expect_phead(q, bn - 1, loop - 1, __LINE__); + expect_chead(q, bn - 1, loop - 1, __LINE__); + + expect_eq_allocated(q, &q->blocks[0], bs, loop - 1, __LINE__); + expect_eq_committed(q, &q->blocks[0], bs, loop - 1, __LINE__); + expect_eq_reserved(q, &q->blocks[0], bs, loop - 1, __LINE__); + expect_eq_consumed(q, &q->blocks[0], bs, loop - 1, __LINE__); + + for (uint32_t i = 1; i < bn; i++) { + expect_eq_allocated(q, &q->blocks[i], bs, loop, __LINE__); + expect_eq_committed(q, &q->blocks[i], bs, loop, __LINE__); + expect_eq_reserved(q, &q->blocks[i], bs, loop, __LINE__); + expect_eq_consumed(q, &q->blocks[i], bs, loop, __LINE__); + } + + EXPECT_TRUE(bbq_debug_check_array_bounds(q)); + bbq_destory(q); +} + +// 完成多轮的满生产和满消费 +TEST_F(bbq_example, head_cursor_produce_all_loop) { + ut_produce_all_loop(1); + ut_produce_all_loop(10); + ut_produce_all_loop(23); + ut_produce_all_loop(79); +} + +TEST_F(bbq_example, head_cursor_retry_new_full_empty) { + int ret = 0; + uint32_t entries_cnt = 4096; + uint32_t loop = 1000; + struct bbq *q; + uint64_t ph = 0; + uint64_t ch = 0; + int *data = (int *)ut_malloc(UT_MODULE_UTEST, sizeof(*data) * entries_cnt); + int tmp_data = 0; + EXPECT_TRUE(data); + + q = bbq_create_elem("ut_bbq", entries_cnt, sizeof(int), BBQ_SOCKET_ID_ANY, + BBQ_F_RETRY_NEW | BBQ_F_ENABLE_STAT, + ut_malloc_def_callback, ut_free_def_callback); + ASSERT_NE(q, nullptr); + EXPECT_TRUE(bbq_empty(q)); + + for (uint32_t i = 0; i < loop; i++) { + // 入满队 + for (uint32_t j = 0; j < entries_cnt; j++) { + data[j] = (i + 1) * j; + ret = bbq_enqueue_elem(q, &data[j]); + EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; + EXPECT_FALSE(bbq_empty(q)); + } + + // 满队再入队 + for (uint32_t j = 0; j < entries_cnt / 3; j++) { + ret = bbq_enqueue_elem(q, &data[j]); + EXPECT_TRUE(ret == BBQ_ERR_FULL); + } + + ph = bbq_atomic64_load(&q->phead.value, q->prod_single); + ch = bbq_atomic64_load(&q->chead.value, q->cons_single); + if (i == 0) { + EXPECT_EQ((ph + 1) & q->idx_mask, ch & q->idx_mask); + } else { + EXPECT_EQ((ph)&q->idx_mask, ch & q->idx_mask); + } + + for (uint32_t i = 0; i < q->bn; i++) { + EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].committed, q->prod_single) & q->off_mask, q->bs); + EXPECT_GE(bbq_atomic64_load(&q->blocks[i].allocated, q->prod_single) & q->off_mask, q->bs); + } + + // 全出队 + for (uint32_t j = 0; j < entries_cnt; j++) { + EXPECT_FALSE(bbq_empty(q)); + ret = bbq_dequeue_elem(q, &tmp_data); + EXPECT_TRUE(ret == BBQ_OK); + EXPECT_EQ(tmp_data, data[j]); + } + + EXPECT_TRUE(bbq_empty(q)); + // 空出队再出队 + for (uint32_t j = 0; j < entries_cnt / 2; j++) { + ret = bbq_dequeue_elem(q, &tmp_data); + EXPECT_TRUE(ret == BBQ_ERR_EMPTY); + } + + ph = bbq_atomic64_load(&q->phead.value, q->prod_single); + ch = bbq_atomic64_load(&q->chead.value, q->cons_single); + EXPECT_EQ(ph & q->idx_mask, ch & q->idx_mask); + for (uint32_t i = 0; i < q->bn; i++) { + EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].committed, q->prod_single) & q->off_mask, q->bs); + EXPECT_GE(bbq_atomic64_load(&q->blocks[i].allocated, q->prod_single) & q->off_mask, q->bs); + EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].consumed, q->cons_single) & q->off_mask, q->bs); + EXPECT_GE(bbq_atomic64_load(&q->blocks[i].reserved, q->cons_single) & q->off_mask, q->bs); + } + } + + ut_free(UT_MODULE_UTEST, data); + EXPECT_TRUE(bbq_debug_check_array_bounds(q)); + bbq_destory(q); +} + +TEST_F(bbq_example, head_cursor_mpsc_faa) { + struct ut_info_s info = { + .cfg = { + .base = { + .name = {}, + .introduce = {}, + .cores_cnt = 4, + }, + .ring = { + .ring_type = UT_RING_TYPE_BBQ, + .producer_cnt = 10, + .consumer_cnt = 1, + .workload = UT_WORKLOAD_SIMPLE, + .entries_cnt = 4, + .block_count = 1, + .burst_cnt = 1, + }, + .run = { + .run_ok_times = 9000000, + .run_time = 0, + }, + }, + .ctl = { + .running = true, + .all_threads_start = {}, + .producer_exit = {}, + }, + }; + + // 队列初始化 + int ret = -1; + struct ut_queue q; + ret = ut_queue_init_bbq(&info.cfg, &q); + ASSERT_TRUE(ret == 0); + + // 创建线程 + pthread_t *threads = ut_threads_create(&info, &q); + ASSERT_TRUE(threads); + + // 等待所有线程完成,回收数据 + uint32_t thread_cnt = info.cfg.ring.producer_cnt + info.cfg.ring.consumer_cnt; + struct ut_exit_data **exit_data = (struct ut_exit_data **)ut_malloc(UT_MODULE_UTEST, sizeof(struct ut_exit_data **) * (thread_cnt)); + uint32_t i = 0; + + ut_wait_all_threads_exit(&info, thread_cnt, threads, exit_data); + + // 比较数据 + struct ut_merge_s merge; + memset(&merge, 0, sizeof(merge)); + + ut_merge_all_data(exit_data, thread_cnt, &merge); + EXPECT_EQ(merge.consumer.data_error_cnt, 0); + EXPECT_EQ(merge.consumer.ok_cnt, merge.producer.ok_cnt); + + // 释放数据 + for (i = 0; i < thread_cnt; i++) { + ut_exit_data_destory(exit_data[i]); + } + ut_free(UT_MODULE_UTEST, exit_data); + ut_threads_destory(&info, threads); + EXPECT_TRUE(bbq_debug_check_array_bounds((struct bbq *)q.ring)); + ut_queue_destory(&q); +} + +TEST_F(bbq_example, head_cursor_drop_old_full_empty) { + int ret = 0; + uint32_t bn = 2; + uint32_t bs = 4; + uint32_t loop = 1000; + struct bbq *q; + + int tmp_data = 0; + q = bbq_create_elem_with_bnbs("ut_bbq", bn, bs, sizeof(int), + BBQ_SOCKET_ID_ANY, BBQ_F_DROP_OLD, + ut_malloc_def_callback, ut_free_def_callback); + ASSERT_NE(q, nullptr); + // EXPECT_TRUE(bbq_empty(q)); + + for (uint32_t j = 0; j < loop; j++) { + // 入满队列 + for (uint32_t i = 0; i < bn * bs; i++) { + ret = bbq_enqueue_elem(q, &i); + EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; + // EXPECT_FALSE(bbq_empty(q)); + } + + // 全出队 + for (uint32_t i = 0; i < bn * bs; i++) { + // EXPECT_FALSE(bbq_empty(q)); + ret = bbq_dequeue_elem(q, &tmp_data); + EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; + EXPECT_EQ(tmp_data, i); + } + + // EXPECT_TRUE(bbq_empty(q)); + // 空队再出队,失败 + for (uint32_t i = 0; i < bn * bs; i++) { + ret = bbq_dequeue_elem(q, &tmp_data); + EXPECT_TRUE(ret == BBQ_ERR_EMPTY) << "ret " << ret; + } + + expect_phead(q, bn - 1, j, __LINE__); + expect_chead(q, bn - 1, j, __LINE__); + for (uint32_t i = 0; i < q->bn; i++) { + expect_eq_committed(q, &q->blocks[i], q->bs, i == 0 ? j : j + 1, __LINE__); + expect_eq_allocated(q, &q->blocks[i], q->bs, i == 0 ? j : j + 1, __LINE__); + expect_eq_reserved(q, &q->blocks[i], q->bs, i == 0 ? j : j + 1, __LINE__); + EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].consumed, q->cons_single), 0); + } + } + EXPECT_TRUE(bbq_debug_check_array_bounds(q)); + bbq_destory(q); +} + +TEST_F(bbq_example, head_cursor_drop_old_full_empty_cover) { + int ret = 0; + uint32_t bn = 2; + uint32_t bs = 4; + uint32_t loop = 1000; + uint32_t over_cnt = bs + 2; + struct bbq *q; + + EXPECT_EQ(over_cnt / bs, 1); + + int tmp_data = 0; + q = bbq_create_elem_with_bnbs("ut_bbq", bn, bs, sizeof(int), + BBQ_SOCKET_ID_ANY, BBQ_F_DROP_OLD, + ut_malloc_def_callback, ut_free_def_callback); + ASSERT_NE(q, nullptr); + + // EXPECT_TRUE(bbq_empty(q)); + // 入满队列,再入over_cnt + for (uint32_t i = 0; i < bn * bs * loop + over_cnt; i++) { + ret = bbq_enqueue_elem(q, &i); + EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; + + // uint32_t tmpA = i / (bn * bs); + // uint32_t tmpB = i % (bn * bs); + // if (tmpA > 0 && (tmpB < bs)) { + // // 覆盖第一个块时,整个块被作废,因此都是empty,从第二个块开始可读取 + // EXPECT_TRUE(bbq_empty(q)) << "i " << i << "tmpA " << tmpA << "tmpB " << tmpB; + // } else { + // EXPECT_FALSE(bbq_empty(q)); + // } + } + + expect_phead(q, 1, loop, __LINE__); + expect_chead(q, 0, 0, __LINE__); + // 检查每一个block上游标的正确性 + for (uint32_t i = 0; i < bn; i++) { + expect_eq_committed(q, &q->blocks[i], + i == bn - 1 ? over_cnt - bs : bs, + i == 0 ? loop : loop + 1, + __LINE__); + expect_eq_allocated(q, &q->blocks[i], + i == bn - 1 ? over_cnt - bs : bs, + i == 0 ? loop : loop + 1, + __LINE__); + expect_eq_reserved(q, &q->blocks[i], + i == 0 ? 0 : bs, 0, + __LINE__); + EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].consumed, false), 0); + } + + // 队列中的数据全出队 + for (uint32_t i = 0; i < over_cnt - bs; i++) { + ret = bbq_dequeue_elem(q, &tmp_data); + EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; + } + + for (uint32_t i = 0; i < bn * bs; i++) { + // EXPECT_TRUE(bbq_empty(q)); + ret = bbq_dequeue_elem(q, &tmp_data); + EXPECT_TRUE(ret == BBQ_ERR_EMPTY) << "ret " << ret; + } + + expect_chead(q, 1, 0, __LINE__); + for (uint32_t i = 0; i < bn; i++) { + expect_eq_committed(q, &q->blocks[i], + i == bn - 1 ? over_cnt - bs : bs, + i == 0 ? loop : loop + 1, + __LINE__); + expect_eq_allocated(q, &q->blocks[i], + i == bn - 1 ? over_cnt - bs : bs, + i == 0 ? loop : loop + 1, + __LINE__); + expect_eq_reserved(q, &q->blocks[i], + i == bn - 1 ? over_cnt - bs : bs, + i == 1 ? loop + 1 : 0, __LINE__); + EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].consumed, false), 0); } EXPECT_TRUE(bbq_debug_check_array_bounds(q)); diff --git a/bbq/tests/unittest/ut_head_cursor.cc b/bbq/tests/unittest/ut_head_cursor.cc deleted file mode 100644 index e5bc9c6..0000000 --- a/bbq/tests/unittest/ut_head_cursor.cc +++ /dev/null @@ -1,550 +0,0 @@ -/* - * @Author: liuyu - * @LastEditTime: 2024-07-07 15:01:06 - * @Email: [email protected] - * @Describe: TODO - */ -#include "gtest/gtest.h" -extern "C" { -#include "test_queue.h" -#include "ut.h" -extern bool bbq_debug_check_array_bounds(struct bbq *q); -extern struct bbq *bbq_create_elem_with_bnbs(const char *name, uint32_t bn, uint32_t bs, - size_t obj_size, int socket_id, uint32_t flags, - bbq_malloc_f malloc_f, bbq_free_f free_f); -extern uint64_t bbq_atomic64_load(union bbq_atomic64 *atomic, bool single); -} - -class bbq_head_cursor : public testing::Test { // 继承了 testing::Test - protected: - virtual void SetUp() override { - // std::cout << "enter into SetUp()" << std::endl; - // 清空内存泄漏统计 - test_memory_counter_clear(); - } - - virtual void TearDown() override { - // std::cout << "exit from TearDown" << std::endl; - // 内存泄漏检测 - EXPECT_TRUE(test_malloc_free_equal()); - } -}; - -void expect_phead(struct bbq *q, uint64_t idx, uint64_t vsn, int line) { - uint64_t ph = bbq_atomic64_load(&q->phead.value, q->prod_single); - EXPECT_EQ(bbq_head_idx(q, ph), idx) << "line: " << line; - EXPECT_EQ(bbq_head_vsn(q, ph), vsn) << "line: " << line; -} - -void expect_chead(struct bbq *q, uint64_t idx, uint64_t vsn, int line) { - uint64_t ch = bbq_atomic64_load(&q->chead.value, q->cons_single); - EXPECT_EQ(bbq_head_idx(q, ch), idx) << "line: " << line; - EXPECT_EQ(bbq_head_vsn(q, ch), vsn) << "line: " << line; -} - -void expect_eq_allocated(struct bbq *q, bbq_block *block, uint64_t off, uint64_t vsn, int line) { - uint64_t allocated = bbq_atomic64_load(&block->allocated, q->prod_single); - EXPECT_EQ(bbq_cur_off(q, allocated), off) << "line: " << line; - EXPECT_EQ(bbq_cur_vsn(q, allocated), vsn) << "line: " << line; -} - -void expect_eq_committed(struct bbq *q, bbq_block *block, uint64_t off, uint64_t vsn, int line) { - uint64_t committed = bbq_atomic64_load(&block->committed, q->prod_single); - EXPECT_EQ(bbq_cur_off(q, committed), off) << "line: " << line; - EXPECT_EQ(bbq_cur_vsn(q, committed), vsn) << "line: " << line; -} - -void expect_eq_consumed(struct bbq *q, bbq_block *block, uint64_t off, uint64_t vsn, int line) { - uint64_t consumed = bbq_atomic64_load(&block->consumed, q->cons_single); - EXPECT_EQ(bbq_cur_off(q, consumed), off) << "line: " << line; - EXPECT_EQ(bbq_cur_vsn(q, consumed), vsn) << "line: " << line; -} - -void expect_eq_reserved(struct bbq *q, bbq_block *block, uint64_t off, uint64_t vsn, int line) { - uint64_t reserved = bbq_atomic64_load(&block->reserved, q->cons_single); - EXPECT_EQ(bbq_cur_off(q, reserved), off) << "line: " << line; - EXPECT_EQ(bbq_cur_vsn(q, reserved), vsn) << "line: " << line; -} - -// 初始化状态 -TEST_F(bbq_head_cursor, init) { - struct bbq *q; - uint32_t bn = 2; - uint32_t bs = 4; - q = bbq_create_elem_with_bnbs("test_bbq", bn, bs, sizeof(int), - BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, - test_malloc_def_callback, test_free_def_callback); - ASSERT_NE(q, nullptr); - - // 1.初始化状态,除了第一个block外其他块的4个游标都指向最后一个条目 - - EXPECT_EQ(bbq_atomic64_load(&q->phead.value, q->prod_single), 0); - EXPECT_EQ(bbq_atomic64_load(&q->chead.value, q->cons_single), 0); - - expect_eq_allocated(q, &q->blocks[0], 0, 0, __LINE__); - expect_eq_committed(q, &q->blocks[0], 0, 0, __LINE__); - expect_eq_reserved(q, &q->blocks[0], 0, 0, __LINE__); - expect_eq_consumed(q, &q->blocks[0], 0, 0, __LINE__); - for (uint32_t i = 1; i < bn; i++) { - expect_eq_allocated(q, &q->blocks[i], bs, 0, __LINE__); - expect_eq_committed(q, &q->blocks[i], bs, 0, __LINE__); - expect_eq_reserved(q, &q->blocks[i], bs, 0, __LINE__); - expect_eq_consumed(q, &q->blocks[i], bs, 0, __LINE__); - } - EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - bbq_destory(q); -} - -void ut_produce_something(uint32_t produce_cnt) { - int ret = 0; - struct bbq *q; - uint32_t bn = 8; - uint32_t bs = 4096; - int enqueue_data = TEST_DATA_MAGIC; - int dequeue_data = 0; - - EXPECT_GT(produce_cnt, 0); - EXPECT_LE(produce_cnt, bs); - - q = bbq_create_elem_with_bnbs("test_bbq", bn, bs, sizeof(int), - BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, - test_malloc_def_callback, test_free_def_callback); - ASSERT_NE(q, nullptr); - - // 生产produce_cnt - for (uint32_t i = 0; i < produce_cnt; i++) { - ret = bbq_enqueue_elem(q, &enqueue_data); - EXPECT_TRUE(ret == BBQ_OK); - } - - EXPECT_EQ(bbq_atomic64_load(&q->phead.value, q->prod_single), 0); - EXPECT_EQ(bbq_atomic64_load(&q->chead.value, q->cons_single), 0); - expect_eq_allocated(q, &q->blocks[0], produce_cnt, 0, __LINE__); - expect_eq_committed(q, &q->blocks[0], produce_cnt, 0, __LINE__); - expect_eq_reserved(q, &q->blocks[0], 0, 0, __LINE__); - expect_eq_consumed(q, &q->blocks[0], 0, 0, __LINE__); - - // 消费完 - for (uint32_t i = 0; i < produce_cnt; i++) { - ret = bbq_dequeue_elem(q, &dequeue_data); - EXPECT_TRUE(ret == BBQ_OK); - EXPECT_EQ(dequeue_data, TEST_DATA_MAGIC); - } - - EXPECT_EQ(bbq_atomic64_load(&q->phead.value, q->prod_single), 0); - EXPECT_EQ(bbq_atomic64_load(&q->chead.value, q->cons_single), 0); - expect_eq_allocated(q, &q->blocks[0], produce_cnt, 0, __LINE__); - expect_eq_committed(q, &q->blocks[0], produce_cnt, 0, __LINE__); - expect_eq_reserved(q, &q->blocks[0], produce_cnt, 0, __LINE__); - expect_eq_consumed(q, &q->blocks[0], produce_cnt, 0, __LINE__); - - for (uint32_t i = 1; i < bn; i++) { - expect_eq_allocated(q, &q->blocks[i], bs, 0, __LINE__); - expect_eq_committed(q, &q->blocks[i], bs, 0, __LINE__); - expect_eq_reserved(q, &q->blocks[i], bs, 0, __LINE__); - expect_eq_consumed(q, &q->blocks[i], bs, 0, __LINE__); - } - EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - bbq_destory(q); -} -// 在第一块内生产,然后被消费完 -TEST_F(bbq_head_cursor, produce_something) { - ut_produce_something(1); - ut_produce_something(567); - ut_produce_something(789); - ut_produce_something(4096); -} - -void ut_produce_next_block(uint32_t over) { - int ret = 0; - struct bbq *q; - uint32_t bn = 8; - uint32_t bs = 4096; - uint32_t produce_cnt = bs + over; - int enqueue_data = TEST_DATA_MAGIC; - int dequeue_data = 0; - - EXPECT_GT(over, 0); - EXPECT_LT(over, bs); - - q = bbq_create_elem_with_bnbs("test_bbq", bn, bs, sizeof(int), - BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, - test_malloc_def_callback, test_free_def_callback); - ASSERT_NE(q, nullptr); - - // 生产至第二块的第一个entry - for (uint32_t i = 0; i < produce_cnt; i++) { - ret = bbq_enqueue_elem(q, &enqueue_data); - EXPECT_TRUE(ret == BBQ_OK); - } - - EXPECT_EQ(bbq_atomic64_load(&q->chead.value, q->cons_single), 0); - expect_phead(q, 1, 0, __LINE__); - expect_eq_allocated(q, &q->blocks[0], bs, 0, __LINE__); - expect_eq_committed(q, &q->blocks[0], bs, 0, __LINE__); - expect_eq_reserved(q, &q->blocks[0], 0, 0, __LINE__); - expect_eq_consumed(q, &q->blocks[0], 0, 0, __LINE__); - - expect_eq_allocated(q, &q->blocks[1], over, 1, __LINE__); - expect_eq_committed(q, &q->blocks[1], over, 1, __LINE__); - expect_eq_reserved(q, &q->blocks[1], bs, 0, __LINE__); - expect_eq_consumed(q, &q->blocks[1], bs, 0, __LINE__); - - // 消费完 - for (uint32_t i = 0; i < produce_cnt; i++) { - ret = bbq_dequeue_elem(q, &dequeue_data); - EXPECT_TRUE(ret == BBQ_OK); - EXPECT_EQ(dequeue_data, TEST_DATA_MAGIC); - } - - expect_phead(q, 1, 0, __LINE__); - expect_chead(q, 1, 0, __LINE__); - expect_eq_allocated(q, &q->blocks[0], bs, 0, __LINE__); - expect_eq_committed(q, &q->blocks[0], bs, 0, __LINE__); - expect_eq_reserved(q, &q->blocks[0], bs, 0, __LINE__); - expect_eq_consumed(q, &q->blocks[0], bs, 0, __LINE__); - - expect_eq_allocated(q, &q->blocks[1], over, 1, __LINE__); - expect_eq_committed(q, &q->blocks[1], over, 1, __LINE__); - expect_eq_reserved(q, &q->blocks[1], over, 1, __LINE__); - expect_eq_consumed(q, &q->blocks[1], over, 1, __LINE__); - - EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - bbq_destory(q); -} - -// 第一块生产完毕,第二块生产了若干,然后被消费完 -TEST_F(bbq_head_cursor, produce_next_block) { - ut_produce_next_block(1); - ut_produce_next_block(123); - ut_produce_next_block(456); - ut_produce_next_block(4095); -} - -void ut_produce_all_loop(uint32_t loop) { - int ret = 0; - struct bbq *q; - uint32_t bn = 8; - uint32_t bs = 4096; - uint32_t produce_cnt = bn * bs; - int enqueue_data = TEST_DATA_MAGIC; - int dequeue_data = 0; - - q = bbq_create_elem_with_bnbs("test_bbq", bn, bs, sizeof(int), - BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, - test_malloc_def_callback, test_free_def_callback); - ASSERT_NE(q, nullptr); - - for (uint32_t cnt = 0; cnt < loop; cnt++) { - // 所有entry生产完毕 - for (uint32_t i = 0; i < produce_cnt; i++) { - ret = bbq_enqueue_elem(q, &enqueue_data); - EXPECT_TRUE(ret == BBQ_OK); - } - - // 消费完 - for (uint32_t i = 0; i < produce_cnt; i++) { - ret = bbq_dequeue_elem(q, &dequeue_data); - EXPECT_TRUE(ret == BBQ_OK); - EXPECT_EQ(dequeue_data, TEST_DATA_MAGIC); - } - } - - expect_phead(q, bn - 1, loop - 1, __LINE__); - expect_chead(q, bn - 1, loop - 1, __LINE__); - - expect_eq_allocated(q, &q->blocks[0], bs, loop - 1, __LINE__); - expect_eq_committed(q, &q->blocks[0], bs, loop - 1, __LINE__); - expect_eq_reserved(q, &q->blocks[0], bs, loop - 1, __LINE__); - expect_eq_consumed(q, &q->blocks[0], bs, loop - 1, __LINE__); - - for (uint32_t i = 1; i < bn; i++) { - expect_eq_allocated(q, &q->blocks[i], bs, loop, __LINE__); - expect_eq_committed(q, &q->blocks[i], bs, loop, __LINE__); - expect_eq_reserved(q, &q->blocks[i], bs, loop, __LINE__); - expect_eq_consumed(q, &q->blocks[i], bs, loop, __LINE__); - } - - EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - bbq_destory(q); -} - -// 完成多轮的满生产和满消费 -TEST_F(bbq_head_cursor, produce_all_loop) { - ut_produce_all_loop(1); - ut_produce_all_loop(10); - ut_produce_all_loop(23); - ut_produce_all_loop(79); -} - -TEST_F(bbq_head_cursor, retry_new_full_empty) { - int ret = 0; - uint32_t entries_cnt = 4096; - uint32_t loop = 1000; - struct bbq *q; - uint64_t ph = 0; - uint64_t ch = 0; - int *data = (int *)test_malloc(TEST_MODULE_UTEST, sizeof(*data) * entries_cnt); - int tmp_data = 0; - EXPECT_TRUE(data); - - q = bbq_create_elem("test_bbq", entries_cnt, sizeof(int), BBQ_SOCKET_ID_ANY, - BBQ_F_RETRY_NEW | BBQ_F_ENABLE_STAT, - test_malloc_def_callback, test_free_def_callback); - ASSERT_NE(q, nullptr); - EXPECT_TRUE(bbq_empty(q)); - - for (uint32_t i = 0; i < loop; i++) { - // 入满队 - for (uint32_t j = 0; j < entries_cnt; j++) { - data[j] = (i + 1) * j; - ret = bbq_enqueue_elem(q, &data[j]); - EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; - EXPECT_FALSE(bbq_empty(q)); - } - - // 满队再入队 - for (uint32_t j = 0; j < entries_cnt / 3; j++) { - ret = bbq_enqueue_elem(q, &data[j]); - EXPECT_TRUE(ret == BBQ_ERR_FULL); - } - - ph = bbq_atomic64_load(&q->phead.value, q->prod_single); - ch = bbq_atomic64_load(&q->chead.value, q->cons_single); - if (i == 0) { - EXPECT_EQ((ph + 1) & q->idx_mask, ch & q->idx_mask); - } else { - EXPECT_EQ((ph)&q->idx_mask, ch & q->idx_mask); - } - - for (uint32_t i = 0; i < q->bn; i++) { - EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].committed, q->prod_single) & q->off_mask, q->bs); - EXPECT_GE(bbq_atomic64_load(&q->blocks[i].allocated, q->prod_single) & q->off_mask, q->bs); - } - - // 全出队 - for (uint32_t j = 0; j < entries_cnt; j++) { - EXPECT_FALSE(bbq_empty(q)); - ret = bbq_dequeue_elem(q, &tmp_data); - EXPECT_TRUE(ret == BBQ_OK); - EXPECT_EQ(tmp_data, data[j]); - } - - EXPECT_TRUE(bbq_empty(q)); - // 空出队再出队 - for (uint32_t j = 0; j < entries_cnt / 2; j++) { - ret = bbq_dequeue_elem(q, &tmp_data); - EXPECT_TRUE(ret == BBQ_ERR_EMPTY); - } - - ph = bbq_atomic64_load(&q->phead.value, q->prod_single); - ch = bbq_atomic64_load(&q->chead.value, q->cons_single); - EXPECT_EQ(ph & q->idx_mask, ch & q->idx_mask); - for (uint32_t i = 0; i < q->bn; i++) { - EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].committed, q->prod_single) & q->off_mask, q->bs); - EXPECT_GE(bbq_atomic64_load(&q->blocks[i].allocated, q->prod_single) & q->off_mask, q->bs); - EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].consumed, q->cons_single) & q->off_mask, q->bs); - EXPECT_GE(bbq_atomic64_load(&q->blocks[i].reserved, q->cons_single) & q->off_mask, q->bs); - } - } - - test_free(TEST_MODULE_UTEST, data); - EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - bbq_destory(q); -} - -TEST_F(bbq_head_cursor, mpsc_faa) { - test_info_s test_info = { - .cfg = { - .base = { - .name = {}, - .introduce = {}, - .cores_cnt = 4, - }, - .ring = { - .ring_type = TEST_RING_TYPE_BBQ, - .producer_cnt = 10, - .consumer_cnt = 1, - .workload = TEST_WORKLOAD_SIMPLE, - .entries_cnt = 4, - .block_count = 1, - .burst_cnt = 1, - }, - .run = { - .run_ok_times = 9000000, - .run_time = 0, - }, - }, - .ctl = { - .running = true, - .all_threads_start = {}, - .producer_exit = {}, - }, - }; - - // 队列初始化 - int ret = -1; - test_queue_s q; - ret = test_queue_init_bbq(&test_info.cfg, &q); - ASSERT_TRUE(ret == 0); - - // 创建线程 - pthread_t *threads = test_threads_create(&test_info, &q); - ASSERT_TRUE(threads); - - // 等待所有线程完成,回收数据 - uint32_t thread_cnt = test_info.cfg.ring.producer_cnt + test_info.cfg.ring.consumer_cnt; - test_exit_data **exit_data = (test_exit_data **)test_malloc(TEST_MODULE_UTEST, sizeof(test_exit_data **) * (thread_cnt)); - uint32_t i = 0; - - test_wait_all_threads_exit(&test_info, thread_cnt, threads, exit_data); - - // 比较数据 - test_merge_s merge; - memset(&merge, 0, sizeof(merge)); - - test_merge_all_data(exit_data, thread_cnt, &merge); - EXPECT_EQ(merge.consumer.data_error_cnt, 0); - EXPECT_EQ(merge.consumer.ok_cnt, merge.producer.ok_cnt); - - // 释放数据 - for (i = 0; i < thread_cnt; i++) { - test_exit_data_destory(exit_data[i]); - } - test_free(TEST_MODULE_UTEST, exit_data); - test_threads_destory(&test_info, threads); - EXPECT_TRUE(bbq_debug_check_array_bounds((struct bbq *)q.ring)); - test_queue_destory(&q); -} - -TEST_F(bbq_head_cursor, drop_old_full_empty) { - int ret = 0; - uint32_t bn = 2; - uint32_t bs = 4; - uint32_t loop = 1000; - struct bbq *q; - - int tmp_data = 0; - q = bbq_create_elem_with_bnbs("test_bbq", bn, bs, sizeof(int), - BBQ_SOCKET_ID_ANY, BBQ_F_DROP_OLD, - test_malloc_def_callback, test_free_def_callback); - ASSERT_NE(q, nullptr); - // EXPECT_TRUE(bbq_empty(q)); - - for (uint32_t j = 0; j < loop; j++) { - // 入满队列 - for (uint32_t i = 0; i < bn * bs; i++) { - ret = bbq_enqueue_elem(q, &i); - EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; - // EXPECT_FALSE(bbq_empty(q)); - } - - // 全出队 - for (uint32_t i = 0; i < bn * bs; i++) { - // EXPECT_FALSE(bbq_empty(q)); - ret = bbq_dequeue_elem(q, &tmp_data); - EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; - EXPECT_EQ(tmp_data, i); - } - - // EXPECT_TRUE(bbq_empty(q)); - // 空队再出队,失败 - for (uint32_t i = 0; i < bn * bs; i++) { - ret = bbq_dequeue_elem(q, &tmp_data); - EXPECT_TRUE(ret == BBQ_ERR_EMPTY) << "ret " << ret; - } - - expect_phead(q, bn - 1, j, __LINE__); - expect_chead(q, bn - 1, j, __LINE__); - for (uint32_t i = 0; i < q->bn; i++) { - expect_eq_committed(q, &q->blocks[i], q->bs, i == 0 ? j : j + 1, __LINE__); - expect_eq_allocated(q, &q->blocks[i], q->bs, i == 0 ? j : j + 1, __LINE__); - expect_eq_reserved(q, &q->blocks[i], q->bs, i == 0 ? j : j + 1, __LINE__); - EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].consumed, q->cons_single), 0); - } - } - EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - bbq_destory(q); -} - -TEST_F(bbq_head_cursor, drop_old_full_empty_cover) { - int ret = 0; - uint32_t bn = 2; - uint32_t bs = 4; - uint32_t loop = 1000; - uint32_t over_cnt = bs + 2; - struct bbq *q; - - EXPECT_EQ(over_cnt / bs, 1); - - int tmp_data = 0; - q = bbq_create_elem_with_bnbs("test_bbq", bn, bs, sizeof(int), - BBQ_SOCKET_ID_ANY, BBQ_F_DROP_OLD, - test_malloc_def_callback, test_free_def_callback); - ASSERT_NE(q, nullptr); - - // EXPECT_TRUE(bbq_empty(q)); - // 入满队列,再入over_cnt - for (uint32_t i = 0; i < bn * bs * loop + over_cnt; i++) { - ret = bbq_enqueue_elem(q, &i); - EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; - - // uint32_t tmpA = i / (bn * bs); - // uint32_t tmpB = i % (bn * bs); - // if (tmpA > 0 && (tmpB < bs)) { - // // 覆盖第一个块时,整个块被作废,因此都是empty,从第二个块开始可读取 - // EXPECT_TRUE(bbq_empty(q)) << "i " << i << "tmpA " << tmpA << "tmpB " << tmpB; - // } else { - // EXPECT_FALSE(bbq_empty(q)); - // } - } - - expect_phead(q, 1, loop, __LINE__); - expect_chead(q, 0, 0, __LINE__); - // 检查每一个block上游标的正确性 - for (uint32_t i = 0; i < bn; i++) { - expect_eq_committed(q, &q->blocks[i], - i == bn - 1 ? over_cnt - bs : bs, - i == 0 ? loop : loop + 1, - __LINE__); - expect_eq_allocated(q, &q->blocks[i], - i == bn - 1 ? over_cnt - bs : bs, - i == 0 ? loop : loop + 1, - __LINE__); - expect_eq_reserved(q, &q->blocks[i], - i == 0 ? 0 : bs, 0, - __LINE__); - EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].consumed, false), 0); - } - - // 队列中的数据全出队 - for (uint32_t i = 0; i < over_cnt - bs; i++) { - ret = bbq_dequeue_elem(q, &tmp_data); - EXPECT_TRUE(ret == BBQ_OK) << "ret " << ret; - } - - for (uint32_t i = 0; i < bn * bs; i++) { - // EXPECT_TRUE(bbq_empty(q)); - ret = bbq_dequeue_elem(q, &tmp_data); - EXPECT_TRUE(ret == BBQ_ERR_EMPTY) << "ret " << ret; - } - - expect_chead(q, 1, 0, __LINE__); - for (uint32_t i = 0; i < bn; i++) { - expect_eq_committed(q, &q->blocks[i], - i == bn - 1 ? over_cnt - bs : bs, - i == 0 ? loop : loop + 1, - __LINE__); - expect_eq_allocated(q, &q->blocks[i], - i == bn - 1 ? over_cnt - bs : bs, - i == 0 ? loop : loop + 1, - __LINE__); - expect_eq_reserved(q, &q->blocks[i], - i == bn - 1 ? over_cnt - bs : bs, - i == 1 ? loop + 1 : 0, __LINE__); - EXPECT_EQ(bbq_atomic64_load(&q->blocks[i].consumed, false), 0); - } - - EXPECT_TRUE(bbq_debug_check_array_bounds(q)); - bbq_destory(q); -}
\ No newline at end of file diff --git a/bbq/tests/unittest/ut_mix.cc b/bbq/tests/unittest/ut_mix.cc deleted file mode 100644 index e6792c8..0000000 --- a/bbq/tests/unittest/ut_mix.cc +++ /dev/null @@ -1,184 +0,0 @@ -/* - * @Author: liuyu - * @LastEditTime: 2024-07-07 15:01:13 - * @Email: [email protected] - * @Describe: bbq除了队列操作外,其他函数的测试 - */ -#include "gtest/gtest.h" -extern "C" { -#include "test_mix.h" -#include "ut.h" -#include <math.h> -extern bool bbq_check_power_of_two(int n); -extern unsigned bbq_ceil_log2(uint64_t x); -extern uint64_t bbq_fetch_max(union bbq_atomic64 *atomic, uint64_t upd, bool single); -extern bool test_malloc_free_equal(); -extern int bbq_bnbs_calc(uint32_t entries, uint32_t *bn, uint32_t *bs); -extern void bbq_atomic64_store(union bbq_atomic64 *atomic, uint64_t value, bool single); -extern uint64_t bbq_atomic64_load(union bbq_atomic64 *atomic, bool single); -} - -class bbq_mix : public testing::Test { // 继承了 testing::Test - protected: - virtual void SetUp() override { - // std::cout << "enter into SetUp()" << std::endl; - // 清空内存泄漏统计 - test_memory_counter_clear(); - } - - virtual void TearDown() override { - // std::cout << "exit from TearDown" << std::endl; - // 内存泄漏检测 - EXPECT_TRUE(test_malloc_free_equal()); - } -}; - -typedef struct { - uint64_t thread_cnt; - bbq_atomic64 data; - aotmic_uint64 ready_thread_cnt; -} ut_fetch_arg; - -void *fetch_max_thread_func(void *arg) { - ut_fetch_arg *fetch_arg = (ut_fetch_arg *)arg; - fetch_arg->ready_thread_cnt.fetch_add(1); - - while (fetch_arg->ready_thread_cnt.load() != fetch_arg->thread_cnt) { - } - - uint64_t *ret = (uint64_t *)test_malloc(TEST_MODULE_UTEST, sizeof(*ret)); - // 不同线程写入不同的>3的数 - *ret = bbq_fetch_max(&fetch_arg->data, pthread_self() + 3, false); - pthread_exit(ret); -} - -TEST_F(bbq_mix, bbq_fetch_max) { - uint64_t ret = 0; - ut_fetch_arg arg; - - bool single = false; - arg.data.m.store(0); - arg.thread_cnt = 0; - arg.ready_thread_cnt.store(0); - - bbq_atomic64_store(&arg.data, 1, single); // 初始化1 - arg.thread_cnt = 50; - - ret = bbq_fetch_max(&arg.data, 2, single); // max比较后设置为2 - EXPECT_EQ(bbq_atomic64_load(&arg.data, single), 2); - EXPECT_EQ(ret, 1); - - pthread_t *threads = (pthread_t *)test_malloc(TEST_MODULE_UTEST, sizeof(*threads) * arg.thread_cnt); - for (uint64_t i = 0; i < arg.thread_cnt; i++) { - // 多个线程同时fetch_max,输入 > 3的数据 - pthread_create(&threads[i], NULL, fetch_max_thread_func, (void *)&arg); - } - - int eq_cnt = 0; - for (uint64_t i = 0; i < arg.thread_cnt; i++) { - uint64_t *tret; - pthread_join(threads[i], (void **)&tret); // 等待每个线程结束 - if (*tret == 2) { - eq_cnt++; // 统计返回2的个数 - } - test_free(TEST_MODULE_UTEST, tret); - } - - // EXPECT_EQ(eq_cnt, 1); - test_free(TEST_MODULE_UTEST, threads); -} - -TEST_F(bbq_mix, power_of_two) { - uint32_t tmp = 0; - uint32_t max = pow(2, 32) - 1; - - EXPECT_FALSE(bbq_check_power_of_two(0)); - - tmp = 3; - for (uint32_t val = 5; val < max; val *= tmp) { - EXPECT_FALSE(bbq_check_power_of_two(val)); - if (val >= max / tmp) { - break; // 即将越界 - } - } - - tmp = 2; - for (uint32_t val = 1; val < max; val *= tmp) { - EXPECT_TRUE(bbq_check_power_of_two(val)); - if (val >= max / tmp) { - break; - } - } -} - -TEST_F(bbq_mix, bbq_block_number_calc) { - uint32_t tmp = 2; - uint32_t max = pow(2, 32) - 1; - uint32_t bn = 0, bs = 0; - int ret = 0; - - ret = bbq_bnbs_calc(1, &bn, &bs); - EXPECT_EQ(ret, BBQ_ERR_OUT_OF_RANGE); - - for (uint32_t val = 2; val < max; val *= tmp) { - ret = bbq_bnbs_calc(val, &bn, &bs); - EXPECT_EQ(ret, BBQ_OK); - if (val <= 128) { - EXPECT_EQ(bn, 2); - } else if (val <= 2048) { - EXPECT_EQ(bn, 4); - } else if (val <= 32768) { - EXPECT_EQ(bn, 8); - } else if (val <= 524288) { - EXPECT_EQ(bn, 16); - } else if (val <= 8388608) { - EXPECT_EQ(bn, 32); - } else if (val <= 134217728) { - EXPECT_EQ(bn, 64); - } else if (val <= 2147483648) { - EXPECT_EQ(bn, 128); - } else { - EXPECT_TRUE(0); // 异常 - } - - if (val >= max / tmp) { - break; - } - } -} - -#define OFFSETOF(type, member) ((size_t) & ((type *)0)->member) -#define PRINT_OFFSETOF(type, member) printf("Offset of '%s' in '%s' is %zu\n", #member, #type, OFFSETOF(type, member)) -#define PTR_ALIGNED_64(ptr) (((uintptr_t)ptr & (64 - 1)) == 0) -#define SIZE_ALIGNED_64(v) (((sizeof(v)) & (64 - 1)) == 0) - -TEST_F(bbq_mix, bbq_cache_line) { - - // 创建队列 - struct bbq *q = bbq_create("test_bbq", 4096, BBQ_SOCKET_ID_ANY, BBQ_F_RETRY_NEW, - test_malloc_def_callback, test_free_def_callback); - ASSERT_NE(q, nullptr); - - // 首地址64字节对齐 - EXPECT_EQ(PTR_ALIGNED_64(q), true); - - // 关键成员64字节对齐 - EXPECT_EQ(PTR_ALIGNED_64(&q->name), true); - EXPECT_EQ(PTR_ALIGNED_64(&q->socket_id), true); - EXPECT_EQ(PTR_ALIGNED_64(&q->phead.value), true); - EXPECT_EQ(PTR_ALIGNED_64(&q->chead.value), true); - EXPECT_EQ(PTR_ALIGNED_64(&q->blocks), true); - EXPECT_EQ(PTR_ALIGNED_64(&q->blocks[0].committed), true); - EXPECT_EQ(PTR_ALIGNED_64(&q->blocks[0].entries), true); - - EXPECT_EQ(SIZE_ALIGNED_64(struct bbq_head), true); - EXPECT_EQ(SIZE_ALIGNED_64(struct bbq_block), true); - - // PRINT_OFFSETOF(struct bbq, name); - // PRINT_OFFSETOF(struct bbq, socket_id); - // PRINT_OFFSETOF(struct bbq, phead); - // PRINT_OFFSETOF(struct bbq, chead); - // PRINT_OFFSETOF(struct bbq, blocks); - - bbq_destory(q); -}
\ No newline at end of file diff --git a/bbq/tests/unittest/ut_multit.cc b/bbq/tests/unittest/ut_multit.cc deleted file mode 100644 index 754f911..0000000 --- a/bbq/tests/unittest/ut_multit.cc +++ /dev/null @@ -1,91 +0,0 @@ -/* - * @Author: liuyu - * @LastEditTime: 2024-07-04 03:43:33 - * @Email: [email protected] - * @Describe: TODO - */ - -#include "gtest/gtest.h" -extern "C" { -#include "test_mix.h" -#include "test_queue.h" -#include "ut.h" -extern bool test_malloc_free_equal(); -bool bbq_debug_check_array_bounds(struct bbq *q); -} - -class multit : public testing::Test { // 继承了 testing::Test - protected: - virtual void SetUp() override { - // std::cout << "enter into SetUp()" << std::endl; - // 清空内存泄漏统计 - test_memory_counter_clear(); - } - - virtual void TearDown() override { - // std::cout << "exit from TearDown" << std::endl; - // 内存泄漏检测 - EXPECT_TRUE(test_malloc_free_equal()); - } -}; - -TEST_F(multit, mpmc) { - test_info_s test_info{ - .cfg = { - .base = { - .name = {}, - .introduce = {}, - .cores_cnt = 4, - }, - .ring = { - .ring_type = TEST_RING_TYPE_BBQ, - .producer_cnt = 4, - .consumer_cnt = 4, - .workload = TEST_WORKLOAD_SIMPLE, - .entries_cnt = 4096, - .block_count = 0, - .burst_cnt = 4, - }, - .run = { - .run_ok_times = 9000000, - .run_time = 0, - }, - }, - .ctl = { - .running = true, - .all_threads_start = {}, - .producer_exit = {}, - }, - }; - - // 队列初始化 - int ret = -1; - test_queue_s q; - ret = test_queue_init_bbq(&test_info.cfg, &q); - ASSERT_TRUE(ret == 0); - - // 创建线程 - pthread_t *threads = test_threads_create(&test_info, &q); - ASSERT_TRUE(threads); - - // 等待所有线程完成,回收数据 - uint32_t thread_cnt = test_info.cfg.ring.producer_cnt + test_info.cfg.ring.consumer_cnt; - test_exit_data **exit_data = (test_exit_data **)test_malloc(TEST_MODULE_UTEST, sizeof(test_exit_data **) * (thread_cnt)); - test_wait_all_threads_exit(&test_info, thread_cnt, threads, exit_data); - - // 比较数据 - test_merge_s merge; - memset(&merge, 0, sizeof(merge)); - test_merge_all_data(exit_data, thread_cnt, &merge); - EXPECT_EQ(merge.consumer.data_error_cnt, 0); - EXPECT_EQ(merge.consumer.ok_cnt, merge.producer.ok_cnt); - - // 释放数据 - for (uint32_t i = 0; i < thread_cnt; i++) { - test_exit_data_destory(exit_data[i]); - } - test_free(TEST_MODULE_UTEST, exit_data); - test_threads_destory(&test_info, threads); - EXPECT_TRUE(bbq_debug_check_array_bounds((struct bbq *)q.ring)); - test_queue_destory(&q); -} diff --git a/perf/benchmark/bcm_benchmark.c b/perf/benchmark/bcm_benchmark.c index 13b5028..99afb3d 100644 --- a/perf/benchmark/bcm_benchmark.c +++ b/perf/benchmark/bcm_benchmark.c @@ -1,13 +1,12 @@ /* * @Author: liuyu - * @LastEditTime: 2024-07-04 03:43:44 + * @LastEditTime: 2024-07-07 20:56:02 * @Email: [email protected] * @Describe: TODO */ #include "bbq.h" #include "bcm_queue.h" #include "iniparser.h" -#include "test_mix.h" #include "test_queue.h" #include <pthread.h> #include <stdatomic.h> @@ -16,16 +15,16 @@ #include <sys/prctl.h> #include <unistd.h> -void bcm_report_printf(test_cfg *cfg, test_merge_data *data, test_exit_data **raw_data, uint32_t thread_cnt, test_thread_type_e ttype) { +void bcm_report_printf(struct ut_cfg *cfg, struct ut_merge_data *data, struct ut_exit_data **raw_data, uint32_t thread_cnt, enum ut_thread_type ttype) { char name[10] = {0}; double latency_ns = 0; double throughput = 0; - printf("\n---------%s---------\n", ttype == TEST_THREAD_PRODUCER ? "生产者" : "消费者"); - double use_time = test_clock_time_to_double(&data->use_time); + printf("\n---------%s---------\n", ttype == UT_THREAD_PRODUCER ? "生产者" : "消费者"); + double use_time = ut_clock_time_to_double(&data->use_time); printf("执行时间 : %lf 秒\n", use_time); printf("执行次数 : %lu (burst=%u)\n", data->run_times, cfg->ring.burst_cnt); - printf("成功%s : %lu\n", ttype == TEST_THREAD_PRODUCER ? "入队" : "出队", data->ok_cnt); + printf("成功%s : %lu\n", ttype == UT_THREAD_PRODUCER ? "入队" : "出队", data->ok_cnt); printf("数据错误次数 : %lu\n", data->data_error_cnt); // 同时有生产者、消费者时才输出 @@ -38,15 +37,15 @@ void bcm_report_printf(test_cfg *cfg, test_merge_data *data, test_exit_data **ra (cfg->ring.producer_cnt > 1 && cfg->ring.consumer_cnt == 1)) { for (uint32_t i = 0, bbq_head_idx = 1; i < thread_cnt; i++) { if (raw_data[i]->arg->ttype == ttype) { - test_time_metric tmp_time = test_clock_time_sub(raw_data[i]->metric_end, raw_data[i]->metric_start); - throughput = raw_data[i]->ok_cnt / test_clock_time_to_double(&tmp_time); + struct ut_metric tmp_time = ut_clock_time_sub(raw_data[i]->metric_end, raw_data[i]->metric_start); + throughput = raw_data[i]->ok_cnt / ut_clock_time_to_double(&tmp_time); printf(" %s-%d 吞吐 :%.0lf/s (%e/s)", name, bbq_head_idx, throughput, throughput); bbq_head_idx++; } } } - if (ttype == TEST_THREAD_CONSUMER && cfg->ring.workload == TEST_WORKLOAD_COMPLEX) { + if (ttype == UT_THREAD_CONSUMER && cfg->ring.workload == UT_WORKLOAD_COMPLEX) { latency_ns = data->latency_ns * 1.0 / data->ok_cnt; printf("数据延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); } @@ -55,7 +54,7 @@ void bcm_report_printf(test_cfg *cfg, test_merge_data *data, test_exit_data **ra printf("操作延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); } else { latency_ns = data->op_err_latency_ns * 1.0 / (data->run_times - data->ok_cnt); - if (ttype == TEST_THREAD_PRODUCER) { + if (ttype == UT_THREAD_PRODUCER) { printf("满队入队操作延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); } else { printf("空队出队操作延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); @@ -63,21 +62,21 @@ void bcm_report_printf(test_cfg *cfg, test_merge_data *data, test_exit_data **ra } } -void bcm_report_generate(test_cfg *cfg, test_exit_data **exit_data, uint32_t thread_cnt) { - // test_report report; +void bcm_report_generate(struct ut_cfg *cfg, struct ut_exit_data **exit_data, uint32_t thread_cnt) { + // ut_report report; - test_merge_s merge = {0}; - test_merge_all_data(exit_data, thread_cnt, &merge); + struct ut_merge_s merge = {0}; + ut_merge_all_data(exit_data, thread_cnt, &merge); - printf("ring类型: %s\n", test_ring_type_enum2str(cfg->ring.ring_type)); + printf("ring类型: %s\n", ut_ring_type_enum2str(cfg->ring.ring_type)); printf("简介: %s\n", cfg->base.introduce); printf("配置: %s\n", cfg->base.name); if (cfg->ring.producer_cnt > 0) { - bcm_report_printf(cfg, &merge.producer, exit_data, thread_cnt, TEST_THREAD_PRODUCER); + bcm_report_printf(cfg, &merge.producer, exit_data, thread_cnt, UT_THREAD_PRODUCER); } if (cfg->ring.consumer_cnt > 0) { - bcm_report_printf(cfg, &merge.consumer, exit_data, thread_cnt, TEST_THREAD_CONSUMER); + bcm_report_printf(cfg, &merge.consumer, exit_data, thread_cnt, UT_THREAD_CONSUMER); } if (cfg->ring.producer_cnt > 0 && cfg->ring.consumer_cnt > 0) { @@ -101,7 +100,7 @@ int main(int argc, char *argv[]) { config = "/root/code/c/bbq/perf/benchmark/config/compare/case1_simple_spsc.ini"; ring_type = "dpdk"; burst_cnt = 16; - TEST_ERR_LOG("use default config, ringt_type:%s burst:%u config:%s argc:%d", ring_type, burst_cnt, config, argc); + UT_ERR_LOG("use default config, ringt_type:%s burst:%u config:%s argc:%d", ring_type, burst_cnt, config, argc); } char thread_name[128] = {0}; @@ -109,46 +108,46 @@ int main(int argc, char *argv[]) { prctl(PR_SET_NAME, thread_name); // 加载配置 - test_info_s test_info; - if (test_load_config(config, ring_type, burst_cnt, &test_info.cfg) != 0) { - TEST_ERR_LOG("load config error"); + struct ut_info_s info; + if (ut_load_config(config, ring_type, burst_cnt, &info.cfg) != 0) { + UT_ERR_LOG("load config error"); return -1; } // 队列初始化 int ret = -1; - test_queue_s q; - ret = bcm_queue_init(&test_info.cfg, &q); + struct ut_queue q; + ret = bcm_queue_init(&info.cfg, &q); if (ret != 0) { - TEST_ERR_LOG("init failed :%d", ret); + UT_ERR_LOG("init failed :%d", ret); return ret; } // 创建线程 - pthread_t *threads = test_threads_create(&test_info, &q); + pthread_t *threads = ut_threads_create(&info, &q); if (threads == NULL) { - TEST_ERR_LOG("pthread_arr is NULL"); + UT_ERR_LOG("pthread_arr is NULL"); return ret; } // 等待所有线程完成,回收数据 - uint32_t thread_cnt = test_info.cfg.ring.producer_cnt + test_info.cfg.ring.consumer_cnt; - test_exit_data **exit_data = (test_exit_data **)test_malloc(TEST_MODULE_BCM, sizeof(test_exit_data **) * (thread_cnt)); + uint32_t thread_cnt = info.cfg.ring.producer_cnt + info.cfg.ring.consumer_cnt; + struct ut_exit_data **exit_data = (struct ut_exit_data **)ut_malloc(UT_MODULE_BCM, sizeof(struct ut_exit_data **) * (thread_cnt)); uint32_t i = 0; - test_wait_all_threads_exit(&test_info, thread_cnt, threads, exit_data); + ut_wait_all_threads_exit(&info, thread_cnt, threads, exit_data); // 生成benchmark报告 - bcm_report_generate(&test_info.cfg, exit_data, thread_cnt); + bcm_report_generate(&info.cfg, exit_data, thread_cnt); // 回收、释放数据 for (i = 0; i < thread_cnt; i++) { - test_exit_data_destory(exit_data[i]); + ut_exit_data_destory(exit_data[i]); } - test_free(TEST_MODULE_BCM, exit_data); - test_threads_destory(&test_info, threads); - test_queue_destory(&q); - test_memory_counter_print(); + ut_free(UT_MODULE_BCM, exit_data); + ut_threads_destory(&info, threads); + ut_queue_destory(&q); + ut_memory_counter_print(); return 0; }
\ No newline at end of file diff --git a/perf/benchmark/bcm_loadconfig.c b/perf/benchmark/bcm_loadconfig.c index 9968cf9..b527130 100644 --- a/perf/benchmark/bcm_loadconfig.c +++ b/perf/benchmark/bcm_loadconfig.c @@ -1,17 +1,17 @@ /* * @Author: liuyu - * @LastEditTime: 2024-07-02 23:02:53 + * @LastEditTime: 2024-07-07 19:01:27 * @Email: [email protected] * @Describe: TODO */ #include "bbq.h" #include "iniparser.h" -#include "test_mix.h" +#include "test_queue.h" #include <string.h> -int test_load_config(const char *config, const char *ring_type, uint32_t burst_cnt, test_cfg *cfg) { +int ut_load_config(const char *config, const char *ring_type, uint32_t burst_cnt, struct ut_cfg *cfg) { // 加载配置 - TEST_INFO_LOG("load config:%s", config); + UT_INFO_LOG("load config:%s", config); dictionary *ini = iniparser_load(config); if (ini == NULL) { return -1; @@ -26,7 +26,7 @@ int test_load_config(const char *config, const char *ring_type, uint32_t burst_c cfg->base.introduce[sizeof(cfg->base.introduce) - 1] = '\0'; // 手工写上 \0 cfg->base.cores_cnt = iniparser_getint(ini, "base:cores_cnt", 0); char *workload = (char *)iniparser_getstring(ini, "ring:workload", "unknown"); - cfg->ring.workload = test_workload_str2enum(workload); + cfg->ring.workload = ut_workload_str2enum(workload); cfg->ring.entries_cnt = iniparser_getuint64(ini, "ring:entries_cnt", 0); cfg->ring.producer_cnt = iniparser_getint(ini, "ring:producer_cnt", 0); cfg->ring.consumer_cnt = iniparser_getint(ini, "ring:consumer_cnt", 0); @@ -35,47 +35,47 @@ int test_load_config(const char *config, const char *ring_type, uint32_t burst_c cfg->run.run_time = iniparser_getuint64(ini, "run:run_time", 0); // 设置ring_type - cfg->ring.ring_type = test_ring_type_str2enum(ring_type); - if (cfg->ring.ring_type >= TEST_RING_TYPE_MAX) { - TEST_ERR_LOG("unknown ring type:%d", cfg->ring.ring_type); + cfg->ring.ring_type = ut_ring_type_str2enum(ring_type); + if (cfg->ring.ring_type >= UT_RING_TYPE_MAX) { + UT_ERR_LOG("unknown ring type:%d", cfg->ring.ring_type); return -1; } cfg->ring.burst_cnt = burst_cnt; - if (cfg->ring.ring_type == TEST_RING_TYPE_RMIND) { + if (cfg->ring.ring_type == UT_RING_TYPE_RMIND) { // rmind仅支持1个消费者,仅支持burst方式 if (cfg->ring.consumer_cnt > 1) { - TEST_ERR_LOG("ring type:%s only support single consumer", TEST_RING_TYPE_RMIND_STR); + UT_ERR_LOG("ring type:%s only support single consumer", UT_RING_TYPE_RMIND_STR); return -1; } if (cfg->ring.burst_cnt <= 1) { - TEST_ERR_LOG("ring type:%s only support burst_cnt > 1 !", TEST_RING_TYPE_RMIND_STR); + UT_ERR_LOG("ring type:%s only support burst_cnt > 1 !", UT_RING_TYPE_RMIND_STR); return -1; } - if (cfg->ring.workload == TEST_WORKLOAD_COMPLEX) { - TEST_ERR_LOG("ring type:%s only support simple workload !", TEST_RING_TYPE_RMIND_STR); + if (cfg->ring.workload == UT_WORKLOAD_COMPLEX) { + UT_ERR_LOG("ring type:%s only support simple workload !", UT_RING_TYPE_RMIND_STR); return -1; } } if (cfg->run.run_time == 0 && cfg->run.run_ok_times == 0) { - TEST_ERR_LOG("At least one of run_time or run_ok_times is not 0"); + UT_ERR_LOG("At least one of run_time or run_ok_times is not 0"); return -1; } - TEST_INFO_LOG("introduce:%s", cfg->base.introduce); - TEST_INFO_LOG("cores_cnt:%u", cfg->base.cores_cnt); - TEST_INFO_LOG("workload:%s(%u)", workload, cfg->ring.workload); - TEST_INFO_LOG("entries_cnt:%lu", cfg->ring.entries_cnt); - TEST_INFO_LOG("producer_cnt:%u", cfg->ring.producer_cnt); - TEST_INFO_LOG("consumer_cnt:%u", cfg->ring.consumer_cnt); - TEST_INFO_LOG("block_count:%u", cfg->ring.block_count); - TEST_INFO_LOG("run_ok_times:%lu", cfg->run.run_ok_times); - TEST_INFO_LOG("run_time:%lu", cfg->run.run_time); - TEST_INFO_LOG("ring_type:%s(%u)", ring_type, cfg->ring.ring_type); - TEST_INFO_LOG("burst_cnt:%u", burst_cnt); + UT_INFO_LOG("introduce:%s", cfg->base.introduce); + UT_INFO_LOG("cores_cnt:%u", cfg->base.cores_cnt); + UT_INFO_LOG("workload:%s(%u)", workload, cfg->ring.workload); + UT_INFO_LOG("entries_cnt:%lu", cfg->ring.entries_cnt); + UT_INFO_LOG("producer_cnt:%u", cfg->ring.producer_cnt); + UT_INFO_LOG("consumer_cnt:%u", cfg->ring.consumer_cnt); + UT_INFO_LOG("block_count:%u", cfg->ring.block_count); + UT_INFO_LOG("run_ok_times:%lu", cfg->run.run_ok_times); + UT_INFO_LOG("run_time:%lu", cfg->run.run_time); + UT_INFO_LOG("ring_type:%s(%u)", ring_type, cfg->ring.ring_type); + UT_INFO_LOG("burst_cnt:%u", burst_cnt); // 释放dictionary对象 iniparser_freedict(ini); diff --git a/perf/benchmark/bcm_queue.c b/perf/benchmark/bcm_queue.c index 462afcf..b116f25 100644 --- a/perf/benchmark/bcm_queue.c +++ b/perf/benchmark/bcm_queue.c @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-27 22:15:13 + * @LastEditTime: 2024-07-07 20:52:05 * @Email: [email protected] * @Describe: TODO */ @@ -9,7 +9,7 @@ static __rte_always_inline unsigned int bcm_dpdk_ring_enqueue_burst(struct rte_ring *r, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed) { - TEST_AVOID_WARNING(thread_idx); + UT_AVOID_WARNING(thread_idx); int ret = 0; if (wait_consumed) { @@ -23,14 +23,14 @@ bcm_dpdk_ring_enqueue_burst(struct rte_ring *r, void **obj_table, uint32_t n, ui return ret; } -int test_queue_init_dpdk(test_cfg *cfg, test_queue_s *q) { +int ut_queue_init_dpdk(struct ut_cfg *cfg, struct ut_queue *q) { /* generate eal parameters */ const char *eal_args[] = {"bcm_dpdk", "-n", "4", "--proc-type", "auto", "--no-huge", "-m", "2048"}; if (rte_eal_init(RTE_DIM(eal_args), (char **)eal_args) < 0) { return -1; } - q->ring_type = TEST_RING_TYPE_DPDK; + q->ring_type = UT_RING_TYPE_DPDK; unsigned int flags = 0; if (cfg->ring.producer_cnt <= 1) { flags |= RING_F_SP_ENQ; @@ -49,11 +49,11 @@ int test_queue_init_dpdk(test_cfg *cfg, test_queue_s *q) { return BBQ_ERR_INPUT_NULL; } - q->ring_free_f = (test_ring_free_f)rte_ring_free; - q->enqueue_f = (test_ring_enqueue_f)rte_ring_enqueue; - q->dequeue_f = (test_ring_dequeue_f)rte_ring_dequeue; - q->enqueue_burst_f = (test_enqueue_burst_f)bcm_dpdk_ring_enqueue_burst; - q->dequeue_burst_f = (test_dequeue_burst_f)rte_ring_dequeue_burst; + q->ring_free_f = (ut_ring_free_f)rte_ring_free; + q->enqueue_f = (ut_ring_enqueue_f)rte_ring_enqueue; + q->dequeue_f = (ut_ring_dequeue_f)rte_ring_dequeue; + q->enqueue_burst_f = (ut_enqueue_burst_f)bcm_dpdk_ring_enqueue_burst; + q->dequeue_burst_f = (ut_dequeue_burst_f)rte_ring_dequeue_burst; return BBQ_OK; } @@ -62,18 +62,18 @@ unsigned char *rmind_buf; uint16_t worker_cnt; ringbuf_worker_t **rmind_workers; -void test_queue_free_rmind(void *ring) { +void ut_queue_free_rmind(void *ring) { for (uint16_t i = 0; i < worker_cnt; i++) { ringbuf_unregister((ringbuf_t *)ring, rmind_workers[i]); } - test_free(TEST_MODULE_RMIND, rmind_workers); - test_free(TEST_MODULE_RMIND, rmind_buf); - test_free(TEST_MODULE_RMIND, ring); + ut_free(UT_MODULE_RMIND, rmind_workers); + ut_free(UT_MODULE_RMIND, rmind_buf); + ut_free(UT_MODULE_RMIND, ring); } -uint32_t test_enqueue_burst_rmind(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed) { - TEST_AVOID_WARNING(wait_consumed); +uint32_t ut_enqueue_burst_rmind(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed) { + UT_AVOID_WARNING(wait_consumed); uint32_t cnt = 0; int ret = 0; size_t off = 0; @@ -97,9 +97,9 @@ uint32_t test_enqueue_burst_rmind(void *ring, void **obj_table, uint32_t n, uint return cnt; } -uint32_t test_dequeue_burst_rmind(void *ring, void *obj_table, uint32_t n, uint32_t *wait_consumed) { - TEST_AVOID_WARNING(n); - TEST_AVOID_WARNING(wait_consumed); +uint32_t ut_dequeue_burst_rmind(void *ring, void *obj_table, uint32_t n, uint32_t *wait_consumed) { + UT_AVOID_WARNING(n); + UT_AVOID_WARNING(wait_consumed); size_t len = 0; size_t off = 0; size_t per_size = sizeof(void *); @@ -123,24 +123,24 @@ uint32_t test_dequeue_burst_rmind(void *ring, void *obj_table, uint32_t n, uint3 return 0; } -int test_queue_init_rmind(test_cfg *cfg, test_queue_s *q) { +int ut_queue_init_rmind(struct ut_cfg *cfg, struct ut_queue *q) { static size_t ringbuf_obj_size; worker_cnt = cfg->ring.producer_cnt + cfg->ring.consumer_cnt; ringbuf_get_sizes(worker_cnt, &ringbuf_obj_size, NULL); - ringbuf_t *r = test_malloc(TEST_MODULE_RMIND, ringbuf_obj_size); + ringbuf_t *r = ut_malloc(UT_MODULE_RMIND, ringbuf_obj_size); if (r == NULL) { exit(-1); } size_t buf_size = sizeof(void *) * cfg->ring.entries_cnt; - rmind_buf = test_malloc(TEST_MODULE_RMIND, buf_size); + rmind_buf = ut_malloc(UT_MODULE_RMIND, buf_size); if (rmind_buf == NULL) { exit(-1); } ringbuf_setup(r, worker_cnt, buf_size); - rmind_workers = test_malloc(TEST_MODULE_RMIND, sizeof(*rmind_workers) * worker_cnt); + rmind_workers = ut_malloc(UT_MODULE_RMIND, sizeof(*rmind_workers) * worker_cnt); if (rmind_workers == NULL) { exit(-1); } @@ -152,16 +152,16 @@ int test_queue_init_rmind(test_cfg *cfg, test_queue_s *q) { } q->ring = r; - q->ring_free_f = (test_ring_free_f)test_queue_free_rmind; + q->ring_free_f = (ut_ring_free_f)ut_queue_free_rmind; q->enqueue_f = NULL; q->dequeue_f = NULL; - q->enqueue_burst_f = (test_enqueue_burst_f)test_enqueue_burst_rmind; - q->dequeue_burst_f = (test_dequeue_burst_f)test_dequeue_burst_rmind; + q->enqueue_burst_f = (ut_enqueue_burst_f)ut_enqueue_burst_rmind; + q->dequeue_burst_f = (ut_dequeue_burst_f)ut_dequeue_burst_rmind; return 0; } -int bcm_queue_init(test_cfg *cfg, test_queue_s *q) { +int bcm_queue_init(struct ut_cfg *cfg, struct ut_queue *q) { if (cfg == NULL || q == NULL) { return BBQ_ERR_INPUT_NULL; } @@ -170,14 +170,14 @@ int bcm_queue_init(test_cfg *cfg, test_queue_s *q) { int ret = -1; q->ring_type = cfg->ring.ring_type; switch (q->ring_type) { - case TEST_RING_TYPE_DPDK: - ret = test_queue_init_dpdk(cfg, q); + case UT_RING_TYPE_DPDK: + ret = ut_queue_init_dpdk(cfg, q); break; - case TEST_RING_TYPE_BBQ: - ret = test_queue_init_bbq(cfg, q); + case UT_RING_TYPE_BBQ: + ret = ut_queue_init_bbq(cfg, q); break; - case TEST_RING_TYPE_RMIND: - ret = test_queue_init_rmind(cfg, q); + case UT_RING_TYPE_RMIND: + ret = ut_queue_init_rmind(cfg, q); break; default: return BBQ_ERR; diff --git a/perf/benchmark/bcm_queue.h b/perf/benchmark/bcm_queue.h index edb360c..b996088 100644 --- a/perf/benchmark/bcm_queue.h +++ b/perf/benchmark/bcm_queue.h @@ -1,4 +1,10 @@ +/* + * @Author: liuyu + * @LastEditTime: 2024-07-07 20:41:23 + * @Email: [email protected] + * @Describe: TODO + */ #include "rte_ring.h" #include "test_queue.h" -extern int bcm_queue_init(test_cfg *cfg, test_queue_s *q);
\ No newline at end of file +extern int bcm_queue_init(struct ut_cfg *cfg, struct ut_queue *q);
\ No newline at end of file |
