summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorliuyu <[email protected]>2024-07-07 20:56:29 +0800
committerliuyu <[email protected]>2024-07-07 20:56:29 +0800
commit4d5c9b6f26237c4b5f61da362e9decb7bf83ddf4 (patch)
tree7edfb8c4845444a39a62f0e0762ccb9a651829c3
parent87e474bc378fcbda10ad041c3fe3d1e2159fbd43 (diff)
临时提交,修改函数名ut_开头
-rw-r--r--bbq/tests/common/test_mix.c176
-rw-r--r--bbq/tests/common/test_mix.h207
-rw-r--r--bbq/tests/common/test_queue.c460
-rw-r--r--bbq/tests/common/test_queue.h328
-rw-r--r--bbq/tests/unittest/ut.h20
-rw-r--r--bbq/tests/unittest/ut_example.cc826
-rw-r--r--bbq/tests/unittest/ut_head_cursor.cc550
-rw-r--r--bbq/tests/unittest/ut_mix.cc184
-rw-r--r--bbq/tests/unittest/ut_multit.cc91
-rw-r--r--perf/benchmark/bcm_benchmark.c69
-rw-r--r--perf/benchmark/bcm_loadconfig.c50
-rw-r--r--perf/benchmark/bcm_queue.c64
-rw-r--r--perf/benchmark/bcm_queue.h8
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
* @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
* @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
* @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
* @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
* @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
* @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
* @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