diff options
| author | 刘煜 <[email protected]> | 2024-06-18 08:40:56 +0000 |
|---|---|---|
| committer | 刘煜 <[email protected]> | 2024-06-18 08:40:56 +0000 |
| commit | bfe41598d3f28e20360d79a8412f13c9da84b652 (patch) | |
| tree | 72e4b9b63ea0032de78040d34a90340b569c8ee1 | |
| parent | e17067871a24932eb0473af9d3fb2682191c0516 (diff) | |
编码风格、测试用例完善
32 files changed, 1404 insertions, 1025 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 142785d..b185713 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.0) project(BBQ_TOP) +SET(OUTPUT_DIR ${PROJECT_SOURCE_DIR}/build/output) + # 添加子目录 add_subdirectory(bbq) # bbq库 add_subdirectory(perf)# perf目录用于各类消息队列的性能测试,需要依赖dpdk等环境
\ No newline at end of file diff --git a/bbq/CMakeLists.txt b/bbq/CMakeLists.txt index 1714295..77020a8 100644 --- a/bbq/CMakeLists.txt +++ b/bbq/CMakeLists.txt @@ -7,7 +7,18 @@ include_directories( ) # 设置输出目录 -SET(OUTPUT_DIR ${PROJECT_SOURCE_DIR}/build/output) +if(NOT DEFINED OUTPUT_DIR) + # 如果没有被设置,则设置一个默认值 + SET(OUTPUT_DIR ${PROJECT_SOURCE_DIR}/build/output) +endif() + +# 设置编译类型,默认Release +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) +endif() + +add_compile_options(-Wall -Wextra) + # 库生成的路径 set(LIB_PATH ${OUTPUT_DIR}/lib) # 测试程序生成的路径 diff --git a/bbq/include/bbq.h b/bbq/include/bbq.h index 7877cce..0b7921c 100644 --- a/bbq/include/bbq.h +++ b/bbq/include/bbq.h @@ -1,6 +1,6 @@ /* * @Author: [email protected] - * @LastEditTime: 2024-06-14 09:27:35 + * @LastEditTime: 2024-06-18 14:16:54 * @Describe: bbq(Block-based Bounded Queue)头文件 * 参考:https://www.usenix.org/system/files/atc22-wang-jiawei.pdf */ @@ -12,9 +12,6 @@ #include <stdint.h> #include <stdlib.h> -// #define BBQ_MEMORY -// #define BBQ_DEBUG - #ifndef __cplusplus // C #include <stdatomic.h> @@ -30,168 +27,188 @@ using aotmic_uint64 = std::atomic<uint64_t>; #define __BBQ_CACHE_ALIGNED __attribute__((__aligned__(64))) -typedef struct { +struct bbq_block_s { bbq_cursor committed; // 已提交(version|offset) bbq_cursor allocated; // 已分配(version|offset) bbq_cursor reserved; // 已预留(version|offset) - bbq_cursor consumed; // 已消费(version|offset), 在drop-old模式下没用 - char *entries; -} __BBQ_CACHE_ALIGNED bbq_block_s; - -typedef enum { - BBQ_SUCCESS = 0, - BBQ_BLOCK_DONE, // 当前块已的entry已用完,需要移动到下一个块 - BBQ_NO_ENTRY, // 没有条目可以使用 - BBQ_NOT_AVAILABLE, // 当前块不可以用状态(将返回busy) - BBQ_ALLOCATED, // 已分配,返回entry信息 - BBQ_RESERVED, // 已保留,返回entry信息 -} bbq_queue_state_e; - -typedef struct { - uint64_t off; // entry在当前block的偏移(offset) - uint64_t vsn; // allocated游标的版本(vsn) - uint32_t actual_burst; // 实际出入队个数 - bbq_block_s *block; // 指向所在的block -} bbq_entry_desc_s; - -typedef struct { - bbq_queue_state_e state; // 队列状态 - union { - uint64_t vsn; // reserve_entry state==BLOCK_DONE时生效 - bbq_entry_desc_s e; // state为ALLOCATED、RESERVED生效 - }; -} bbq_queue_state_s; - -#define BBQ_F_DEFAULT 0x0 -// flags 第一位控制入队策略,默认是retry new -#define BBQ_F_POLICY_DROP_OLD 0x0001 -#define BBQ_F_POLICY_RETRY_NEW BBQ_F_DEFAULT -#define BBQ_POLIC_DROP_OLD(flags) (flags & BBQ_F_POLICY_DROP_OLD) -#define BBQ_POLIC_RETRY_NEW(flags) (!(flags & BBQ_F_POLICY_DROP_OLD)) - -// flags 第二位控制入队时的数据拷贝策略,默认是copy pointer -#define BBQ_F_COPY_VALUE 0x0002 -#define BBQ_F_COPY_POINTER BBQ_F_DEFAULT -#define BBQ_COPY_VALUE(flags) (flags & BBQ_F_COPY_VALUE) -#define BBQ_COPY_POINTER(flags) (!(flags & BBQ_F_COPY_VALUE)) - -typedef struct { - size_t bs; // 每个block里entries成员的大小 - size_t bn; // blocks个数 - size_t obj_size; - size_t entry_size; - - int32_t socket_id; // 在哪个socket_id上使用libnuma分配内存,-1表示无效,使用malloc分配 - uint32_t flags; - uint32_t idx_bits; - uint32_t off_bits; - - uint64_t idx_mask; - uint64_t off_mask; - bbq_head phead; // 生产者头,指向块的索引(version|idx) - bbq_head chead; // 消费者头,指向块的索引(version|idx) - - bbq_block_s *blocks; // bn大小的动态数组 -} bbq_queue_s; - -// -----------------------------对外接口------------------------------- + bbq_cursor consumed; // 已消费(version|offset)注:在drop-old模式下没用到 + char *entries; // 存储大小可变的entry,分配空间大小:bs * entry_size +} __BBQ_CACHE_ALIGNED; + +struct bbq_s { + size_t bs; // 每个block里entries成员的大小 + size_t bn; // 块(blocks)的个数 + size_t obj_size; // 入队数据的实际大小,int int* int**,都为sizeof(int) + size_t entry_size; // blocks.entries里每个entry的大小 + + int32_t socket_id; // 在哪个socket_id上使用libnuma分配内存,小于0将使用malloc分配 + uint32_t flags; // 标记:retry new 模式,还是drop old模式 + uint32_t idx_bits; // bbq_head里idx所占的位数 + uint32_t off_bits; // bbq_cursor里offset所占的位数 + + uint64_t idx_mask; // idx_bits偏移后的掩码 + uint64_t off_mask; // off_bits偏移后的掩码 + bbq_head phead; // 生产者头,指向块的索引,分为两部分:version|idx + bbq_head chead; // 消费者头,指向块的索引,分为两部分:version|idx + + struct bbq_block_s *blocks; // bn大小的数组 +}; + +// 创建队列时flags可选参数 +// 第一位控制入队策略,默认是retry new +#define BBQ_CREATE_F_DROP_OLD 0x0001 /**< 创建队列时设置为drop old模式(队列满时,覆盖旧数据,入队成功) */ +#define BBQ_CREATE_F_RETRY_NEW 0x0 /**< 默认为retry new模式(队列满时,当前入队失败) */ + +// 第二位控制入队时的数据拷贝策略,默认是copy pointer +#define BBQ_CREATE_F_COPY_VALUE 0x0002 /**< 创建队列时设置为拷贝数值 */ +#define BBQ_CREATE_F_COPY_PTR 0x0 /**< 默认为拷贝指针 */ + /** - * bbq_ring_create系列接口,用于创建并返回bbq队列结构体,功能类似,区别在于是否需要 - * 指定socket,是否手动手动指定块个数(bn),块的大小(bs),即每个块包含的条目数。 - * @param count - * 队列所有条目的个数(总容量),必须大于1,且是2的N次方。将根据公式自动计算块的个数,以及块的大小。 - * 计算公式:log2(blocks) = max(1, ⌊log2(count)/4⌋) 注:⌊ ⌋代表向下取整。 - * @param flags - * 第一位控制入队策略,默认是retry new模式,即队列满了当前入队失败。如果要设置为drop old模式,需要flags|BBQ_F_DROP_OLD - * 第二位控制入队列时,传入的时候指针,还是指针指向的值。默认传入指针,如果要传入指向的值,需要设置flags|BBQ_F_COPY_VALUE - * @param obj_size - * 队列里每个成员的存储大小,如存储int类型数据:sizeof(int) - * @param socket_id - * socket ID,多numa架构下,队列里的空间将针对指定socket调用libnuma库函数分配内存。 - * 当检测到不支持多numa,将转为malloc分配内存。 + * 创建并返回bbq队列结构指针 + * + * @param[in] count + * 队列所有entry的个数(所有块下entry个数的总和),count必须大于1,且是2的N次方。 + * 函数将会根据count自动计算出合理的块个数,并将entry平均分配到每个块里。 + * 计算公式:log2(blocks) = max(1, ⌊log2(count)/4⌋) 注:⌊ ⌋代表向下取整。 + * @param[in] obj_size + * 入队数据的实际大小,int int* int**,都为sizeof(int),因为在burst的时候会传入数组, + * 需要根据数据大小来计算偏移,请正确设置该值。 + * @param[in] flags + * 设置入队策略,通过BBQ_CREATE_F_XX系列宏定义设置flags + * 1)第一位控制入队策略,默认是retry new模式(队列满了当前入队失败)。 + * 如果要设置为drop old模式,需要flags|BBQ_CREATE_F_DROP_OLD + * 2)第二位控制数据入队列时,将"指针"入队,还是将"指针指向的数据"入队。默认入队"指针", + * 如果把"指针指向的数据"入队,需要设置flags|BBQ_CREATE_F_COPY_VALUE + * 3)可以同时设置多个flag,入BBQ_CREATE_F_DROP_OLD|BBQ_CREATE_F_COPY_VALUE * @return - * 非NULL:消息队列结构体指针,用于后续出队入队等操作。 + * 非NULL:消息队列结构体指针,用于后续出队、入队等操作。 * NULL:创建失败。 */ -extern bbq_queue_s *bbq_ring_create(uint32_t count, size_t obj_size, unsigned int flags); -extern bbq_queue_s *bbq_ring_create_with_socket(uint32_t count, size_t obj_size, int socket_id, unsigned int flags); -extern bbq_queue_s *bbq_ring_create_bnbs(uint32_t bn, uint32_t bs, size_t obj_size, unsigned int flags); -extern bbq_queue_s *bbq_ring_create_bnbs_with_socket(uint32_t bn, uint32_t bs, size_t obj_size, int socket_id, unsigned int flags); +extern struct bbq_s *bbq_create(uint32_t count, size_t obj_size, uint32_t flags); /** - * 用于释放消息队列,与bbq_ring_create系列函数成对。 - * @param q - * 队列指针 + * 创建并返回bbq队列结构指针,支持多numa + * + * @param[in] count + * 队列所有entry的个数(所有块下entry个数的总和),count必须大于1,且是2的N次方。 + * 函数将会根据count自动计算出合理的块个数,并将entry平均分配到每个块里。 + * 计算公式:log2(blocks) = max(1, ⌊log2(count)/4⌋) 注:⌊ ⌋代表向下取整。 + * @param[in] flags + * 设置入队策略,通过BBQ_CREATE_F_XX系列宏定义设置flags + * 1)第一位控制入队策略,默认是retry new模式(队列满了当前入队失败)。 + * 如果要设置为drop old模式,需要flags|BBQ_CREATE_F_DROP_OLD + * 2)第二位控制数据入队列时,将"指针"入队,还是将"指针指向的数据"入队。默认入队"指针", + * 如果把"指针指向的数据"入队,需要设置flags|BBQ_CREATE_F_COPY_VALUE + * 3)可以同时设置多个flag,入BBQ_CREATE_F_DROP_OLD|BBQ_CREATE_F_COPY_VALUE + * @param[in] obj_size + * 入队数据的实际大小,int int* int**,都为sizeof(int),因为在burst的时候会传入数组, + * 需要根据数据大小来计算偏移,请正确设置该值。 + * @param[in] socket_id + * 多numa架构下,队列里的空间将针对指定socket调用libnuma库函数分配内存。 + * 当检测到不支持多numa,将转为malloc分配内存。 + * @return + * 非NULL:消息队列结构体指针,用于后续出队入队等操作。 + * NULL:创建失败。 */ -extern void bbq_ring_free(bbq_queue_s *q); +extern struct bbq_s *bbq_create_with_socket(uint32_t count, size_t obj_size, int socket_id, uint32_t flags); /** - * 消息队列入队 - * @param q - * 队列指针 - * @param data - * void *类型,指针也要取地址后传入。例如int a 或 int *a 都传入 (void *)(&a) + * 用于释放消息队列,与bbq_create/bbq_create_with_socket函数成对。 + * + * @param[in] q + * 队列指针 + */ +extern void bbq_ring_free(struct bbq_s *q); + +/** + * 消息队列单个数据入队 + * + * @param[in] q + * 队列指针 + * @param[in] data + * 创建队列时: + * 1)如果flag设置了BBQ_CREATE_F_COPY_VALUE,则传入一维指针,如 int data,如: + * int data,传入&data + * int *data = malloc(sizeof(int));*data = 1; 传入data + * 2)如果flag设置了BBQ_CREATE_F_COPY_PTR,则传入二维指针,如 int *data,如: + * int *data = malloc(sizeof(int));*data = 1; 传入&data * @return - * BBQ_OK 0 :成功 - * BBQ_QUEUE_FULL -1001 : 失败,队列已满 - * BBQ_QUEUE_BUSY -1002 : 失败,队列忙碌中 - * BBQ_ERROR -1 :未知错误 - * BBQ_NULL_PTR -3 :传入空指针 + * 成功返回0,失败返回小于0的错误码。 */ -extern int bbq_enqueue(bbq_queue_s *q, void *data); +extern int bbq_enqueue(struct bbq_s *q, void *data); /** - * 消息队列出队 - * @param q + * 消息队列批量入队(指针入队),尽可能一次入队n个数据,返回实际成功入队个数 + * + * @param[in] q + * 队列指针 + * @param[in] obj_table + * 即将入队的指针数组,将数组里的每个成员(指针)入队 + * @param[in] n + * 尝试一次入队的个数 + * @return + * 返回实际成功入队个数 + */ +extern uint32_t bbq_enqueue_burst_ptr(struct bbq_s *q, void *const *obj_table, uint32_t n); + +/** + * 消息队列批量入队(数据入队),尽可能一次入队n个数据,返回实际成功入队个数 + * + * @param[in] q + * 队列指针 + * @param[in] obj_table + * 即将入队的数组,将数组里的每个成员入队 + * @param[in] n + * 尝试一次入队的个数 + * @return + * 返回实际成功入队个数 + */ +extern uint32_t bbq_enqueue_burst_value(struct bbq_s *q, void const *obj_table, uint32_t n); + +/** + * 消息队列单个数据出队 + * @param[in] q * 队列指针 - * @param deq_data - * 出队成功将复制数据到该参数。 - * 请不要以此判断是否出队列成功,应以return值作为判断依据。 + * @param[in] data + * 创建队列时: + * 1)如果flag设置了BBQ_CREATE_F_COPY_VALUE,则传入一维指针,如: + * int data,传入&data + * int *data = malloc(sizeof(int)),传入data + * 2)如果flag设置了BBQ_CREATE_F_COPY_PTR,则传入二维指针,如: + * int *data = NULL; 传入&data * @return - * BBQ_OK 0 :成功 - * BBQ_QUEUE_BUSY -1002 : 失败,队列忙碌中 - * BBQ_QUEUE_EMPTY -1003 : 失败,队列已空(出队) - * BBQ_ERROR -1 :未知错误 - * BBQ_NULL_PTR -3 :传入空指针 + * 成功返回0,失败返回小于0的错误码。 */ -extern int bbq_dequeue(bbq_queue_s *q, void *deq_data); +extern int bbq_dequeue(struct bbq_s *q, void *data); /** - * 将多个对象从一个环形队列ring取出,直到达到最大数量,或是出队失败 - * @param q + * 消息队列批量出队(指针出队),尽可能一次出队n个数据,返回实际成功出队个数 + * + * @param[in] q * 队列指针 - * @param obj_table - * @param n - * obj_table的成员个数 + * @param[out] obj_table + * 存储出队的数据(指针) + * @param[in] n + * 尝试一次出队的个数 * @return - * 实际出队个数 + * 返回实际成功出队个数 */ -extern uint32_t bbq_dequeue_burst_one_dimensional(bbq_queue_s *q, void *obj_table, uint32_t n); -extern uint32_t bbq_dequeue_burst_two_dimensional(bbq_queue_s *q, void **obj_table, uint32_t n); +extern uint32_t bbq_dequeue_burst_ptr(struct bbq_s *q, void **obj_table, uint32_t n); + /** - * 尝试一次入队多个数据,直到达到最大数量,或是入队失败 + * 消息队列批量出队(数据出队),尽可能一次出队n个数据,返回实际成功出队个数 * - * @param q + * @param[in] q * 队列指针 - * @param obj_table - * @param n - * obj_table的成员个数 + * @param[out] obj_table + * 存储出队的数据 + * @param[in] n + * 尝试一次出队的个数 * @return - * 实际入队个数 + * 返回实际成功出队个数 */ -extern uint32_t bbq_enqueue_burst_one_dimensional(bbq_queue_s *q, void *obj_table, uint32_t n); -extern uint32_t bbq_enqueue_burst_two_dimensional(bbq_queue_s *q, void **obj_table, uint32_t n); - -// -----------------------------用于内存测试------------------------------- -// 当BBQ_MEMORY宏定义开关打开,将对内存分配释放进行统计,方便排查内存泄漏 -typedef enum { - BBQ_MODULE_QUEUE = 0, - BBQ_MODULE_QUEUE_BLOCK_NB, - BBQ_MODULE_QUEUE_BLOCK_ENTRY, - BBQ_MODULE_MAX, -} bbq_module_e; - -// -----------------------------错误码------------------------------- +extern uint32_t bbq_dequeue_burst_value(struct bbq_s *q, void *obj_table, uint32_t n); + // 通用返回码 #define BBQ_OK 0 // 成功 #define BBQ_ERROR -1 // 通用错误 @@ -204,35 +221,4 @@ typedef enum { #define BBQ_QUEUE_BUSY -1002 // 队列忙碌中(入队或出队失败) #define BBQ_QUEUE_EMPTY -1003 // 队列已空(出队失败) -// -----------------------------日志宏定义------------------------------- -#ifdef BBQ_DEBUG -#define BBQ_DBG_LOG(fmt, ...) \ - do { \ - printf("[DBG][%s:%d:%s]" fmt "\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ - } while (0) - -#else -#define BBQ_DBG_LOG(fmt, ...) \ - do { \ - } while (0) -#endif - -#define BBQ_ERR_LOG(fmt, ...) \ - do { \ - printf("\x1b[31m [ERR][%s:%d:%s]" fmt "\x1b[0m\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ - } while (0) - -#define BBQ_INFO_LOG(fmt, ...) \ - do { \ - printf("[INFO][%s:%d:%s]" fmt "\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ - } while (0) - -#define BBQ_COLOR_PRINT(fmt, ...) \ - do { \ - printf("\033[32m" fmt "\033[0m\n", ##__VA_ARGS__); \ - } while (0) - -// -----------------------------其他宏定义------------------------------- -#define BBQ_INVALID_SOCKET -1 - #endif
\ No newline at end of file diff --git a/bbq/src/bbq.c b/bbq/src/bbq.c index cea7a54..cab4234 100644 --- a/bbq/src/bbq.c +++ b/bbq/src/bbq.c @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 23:11:20 + * @LastEditTime: 2024-06-18 15:03:00 * @Email: [email protected] * @Describe: bbq(Block-based Bounded Queue)实现 * 参考:https://www.usenix.org/system/files/atc22-wang-jiawei.pdf @@ -11,36 +11,135 @@ #include <stdio.h> #include <string.h> +// -----------------------------日志宏定义------------------------------- +#define BBQ_ERR_LOG(fmt, ...) \ + do { \ + printf("\x1b[31m [ERR][%s:%d:%s]" fmt "\x1b[0m\n", __func__, __LINE__, __FILE__, ##__VA_ARGS__); \ + } while (0) + +// -----------------------------其他宏定义------------------------------- +#define AVOID_WARNING(param) ((void)param) +#define BBQ_INVALID_SOCKET -1 + +#define BBQ_POLIC_DROP_OLD(flags) (flags & BBQ_F_POLICY_DROP_OLD) +#define BBQ_POLIC_RETRY_NEW(flags) (!(flags & BBQ_CREATE_F_DROP_OLD)) + +#define BBQ_COPY_VALUE(flags) (flags & BBQ_F_COPY_VALUE) +#define BBQ_COPY_POINTER(flags) (!(flags & BBQ_CREATE_F_COPY_VALUE)) + +// -----------------------------用于内存测试------------------------------- +// 当BBQ_MEMORY宏定义开关打开,将对内存分配释放进行统计,方便排查内存泄漏 +// #define BBQ_MEMORY +enum bbq_module_e { + BBQ_MODULE_QUEUE = 0, + BBQ_MODULE_QUEUE_BLOCK_NB, + BBQ_MODULE_QUEUE_BLOCK_ENTRY, + BBQ_MODULE_MAX, +}; + struct bbq_status { - int32_t status; // 返回状态 - uint32_t actual_burst; // 实际出/入队个数 + int32_t status; // 返回状态 + uint32_t actual_burst; // 实际出/入队个数 +}; + +enum bbq_queue_state_e { + BBQ_SUCCESS = 0, + BBQ_BLOCK_DONE, // 当前块已的entry已用完,需要移动到下一个块 + BBQ_NO_ENTRY, // 没有条目可以使用 + BBQ_NOT_AVAILABLE, // 当前块不可以用状态(将返回busy) + BBQ_ALLOCATED, // 已分配,返回entry信息 + BBQ_RESERVED, // 已保留,返回entry信息 +}; + +struct bbq_entry_desc_s { + uint64_t off; // entry在当前block的偏移(offset) + uint64_t vsn; // allocated游标的版本(vsn) + uint32_t actual_burst; // 实际出入队个数 + struct bbq_block_s *block; // 指向所在的block +}; + +struct bbq_queue_state_s { + enum bbq_queue_state_e state; // 队列状态 + union { + uint64_t vsn; // reserve_entry state==BLOCK_DONE时生效 + struct bbq_entry_desc_s e; // state为ALLOCATED、RESERVED生效 + }; }; +extern inline uint64_t bbq_idx(struct bbq_s *q, uint64_t x) { + return x & q->idx_mask; +} + +extern inline uint64_t bbq_off(struct bbq_s *q, uint64_t x) { + return x & q->off_mask; +} + +extern inline uint64_t bbq_head_vsn(struct bbq_s *q, uint64_t x) { + return x >> q->idx_bits; +} + +extern inline uint64_t bbq_cur_vsn(struct bbq_s *q, uint64_t x) { + return x >> q->off_bits; +} + +extern inline uint64_t set_cur_vsn(struct bbq_s *q, uint64_t ver) { + return ver << q->off_bits; +} + +#ifdef BBQ_MEMORY #define BBQ_MEM_MAGIC 0xFF +#endif + +#ifdef BBQ_MEMORY +struct bbq_memory_s { + aotmic_uint64 malloc_cnt; + aotmic_uint64 malloc_size; + aotmic_uint64 free_cnt; + aotmic_uint64 free_size; +}; +struct bbq_memory_s bbq_memory_g[BBQ_MODULE_MAX] = {0}; +#endif + +void *bbq_malloc(enum bbq_module_e module, int socket_id, size_t size) { + void *ptr = NULL; + if (socket_id >= 0) { + ptr = numa_alloc_onnode(size, 0); + } else { + ptr = malloc(size); + } +#ifdef BBQ_MEMORY + if (ptr != NULL) { + atomic_fetch_add(&bbq_memory_g[module].malloc_cnt, 1); + atomic_fetch_add(&bbq_memory_g[module].malloc_size, size); + } +#else + AVOID_WARNING(module); +#endif + return ptr; +} + +void bbq_free(enum bbq_module_e module, int socket_id, void *ptr, size_t size) { + if (socket_id >= 0) { + numa_free(ptr, size); + } else { + free(ptr); + } -extern bbq_queue_state_s allocate_entry(bbq_queue_s* q, bbq_block_s* block, uint32_t n); -extern bbq_queue_state_e advance_phead(bbq_queue_s* q, uint64_t ph); -extern bbq_queue_state_s reserve_entry(bbq_queue_s* q, bbq_block_s* block, uint32_t n); -extern bool consume_entry(bbq_queue_s* q, bbq_entry_desc_s* e, void* deq_data, uint32_t flag); -extern bool advance_chead(bbq_queue_s* q, uint64_t ch, uint64_t ver); -extern inline uint64_t bbq_idx(bbq_queue_s* q, uint64_t x); -extern inline uint64_t bbq_off(bbq_queue_s* q, uint64_t x); -extern inline uint64_t bbq_head_vsn(bbq_queue_s* q, uint64_t x); -extern inline uint64_t bbq_cur_vsn(bbq_queue_s* q, uint64_t x); -extern inline uint64_t set_cur_vsn(bbq_queue_s* q, uint64_t ver); -extern void* bbq_memset(void* data, size_t size); -extern void* bbq_malloc(bbq_module_e module, int socket_id, size_t size); -extern void bbq_free(bbq_module_e module, int socket_id, void* ptr, size_t size); - -#ifdef BBQ_DEBUG -extern void bbq_struct_print(bbq_queue_s* q); +#ifdef BBQ_MEMORY + if (ptr != NULL) { + atomic_fetch_add(&bbq_memory_g[module].free_cnt, 1); + atomic_fetch_add(&bbq_memory_g[module].free_size, size); + } +#else + AVOID_WARNING(module); #endif +} /* 原子的比较两个值大小,并设置较大的值,成功则返回设置前的旧值 */ -uint64_t fetch_max(aotmic_uint64* atom, uint64_t upd) { +uint64_t fetch_max(aotmic_uint64 *atom, uint64_t upd) { uint64_t old_value; do { - old_value = atomic_load(atom); // 读取当前值 + old_value = atomic_load(atom); // 读取当前值 } while (old_value < upd && !atomic_compare_exchange_weak(atom, &old_value, upd)); return old_value; @@ -59,19 +158,19 @@ bool bbq_check_power_of_two(uint32_t n) { * 计算公式:log2(blocks) = max(1, ⌊log2(count)/4⌋) 注:⌊ ⌋代表向下取整。*/ uint32_t bbq_blocks_calc(uint32_t entries) { double log_entries = log2((double)entries); - uint32_t over4 = (uint32_t)(log_entries / 4); // 向下取整 + uint32_t over4 = (uint32_t)(log_entries / 4); // 向下取整 uint32_t max_value = (over4 > 1) ? over4 : 1; uint32_t n = pow(2, max_value); return n; } /* 块初始化 */ -int block_init(bbq_queue_s* q, bbq_block_s* block, bool cursor_init) { +int block_init(struct bbq_s *q, struct bbq_block_s *block, bool cursor_init) { #ifdef BBQ_MEMORY // 末尾多分配一个entry(永远不应该被修改),以此检查是否存在写越界的问题 block->entries = bbq_malloc(BBQ_MODULE_QUEUE_BLOCK_ENTRY, q->socket_id, (q->bs + 1) * q->entry_size); - char* last_entry = block->entries + q->entry_size * q->bs; + char *last_entry = block->entries + q->entry_size * q->bs; memset(last_entry, BBQ_MEM_MAGIC, q->entry_size); #else block->entries = bbq_malloc(BBQ_MODULE_QUEUE_BLOCK_ENTRY, q->socket_id, @@ -104,7 +203,7 @@ int block_init(bbq_queue_s* q, bbq_block_s* block, bool cursor_init) { } /* 块清理函数,与block_init成对*/ -void block_cleanup(bbq_queue_s* q, bbq_block_s* block) { +void block_cleanup(struct bbq_s *q, struct bbq_block_s *block) { if (block->entries) { #ifdef BBQ_MEMORY bbq_free(BBQ_MODULE_QUEUE_BLOCK_ENTRY, q->socket_id, @@ -137,17 +236,16 @@ unsigned ceil_log2(uint64_t x) { } /* 创建消息队列,bn和bs必须是2的N次幂,socket_id用于多numa分配内存,free_func先设置NULL */ -bbq_queue_s* bbq_ring_create_bnbs_with_socket(uint32_t bn, uint32_t bs, size_t obj_size, int socket_id, unsigned int flags) { +struct bbq_s *bbq_ring_create_bnbs_with_socket(uint32_t bn, uint32_t bs, size_t obj_size, int socket_id, uint32_t flags) { int ret = 0; - bool numa_enable = true; if (bbq_check_power_of_two(bn) == false) { - BBQ_ERR_LOG("block number is not power of two, now is :%lu", bn); + BBQ_ERR_LOG("block number is not power of two, now is :%u", bn); return NULL; } if (bbq_check_power_of_two(bs) == false) { - BBQ_ERR_LOG("block size is not power of two, now is :%lu", bs); + BBQ_ERR_LOG("block size is not power of two, now is :%u", bs); return NULL; } @@ -161,18 +259,18 @@ bbq_queue_s* bbq_ring_create_bnbs_with_socket(uint32_t bn, uint32_t bs, size_t o socket_id = BBQ_INVALID_SOCKET; } - bbq_queue_s* q = bbq_malloc(BBQ_MODULE_QUEUE, socket_id, sizeof(*q)); + struct bbq_s *q = bbq_malloc(BBQ_MODULE_QUEUE, socket_id, sizeof(*q)); if (q == NULL) { BBQ_ERR_LOG("malloc for bbq queue error"); return NULL; } - bbq_memset(q, sizeof(*q)); + memset(q, 0, sizeof(*q)); q->bn = bn; q->bs = bs; q->obj_size = obj_size; if (BBQ_COPY_POINTER(flags)) { - q->entry_size = sizeof(void*); + q->entry_size = sizeof(void *); } else { q->entry_size = obj_size; } @@ -186,7 +284,7 @@ bbq_queue_s* bbq_ring_create_bnbs_with_socket(uint32_t bn, uint32_t bs, size_t o BBQ_ERR_LOG("bbq malloc for blocks error"); goto error; } - bbq_memset(q->blocks, sizeof(*q->blocks)); + memset(q->blocks, 0, sizeof(*q->blocks)); for (uint32_t i = 0; i < bn; ++i) { // 第一个block不需要设置cursor_init_flag @@ -212,14 +310,14 @@ error: } /* 创建消息队列,bn和bs必须是2的N次幂,free_func先设置NULL */ -bbq_queue_s* bbq_ring_create_bnbs(uint32_t bn, uint32_t bs, size_t obj_size, unsigned int flags) { +struct bbq_s *bbq_ring_create_bnbs(uint32_t bn, uint32_t bs, size_t obj_size, unsigned int flags) { return bbq_ring_create_bnbs_with_socket(bn, bs, obj_size, BBQ_INVALID_SOCKET, flags); } /* 创建消息队列,count必须大于1,且是2的N次幂,bn和bs将根据count值自动计算,socket_id用于多numa分配内存,free_func先设置NULL */ -bbq_queue_s* bbq_ring_create_with_socket(uint32_t count, size_t obj_size, int socket_id, unsigned int flags) { +struct bbq_s *bbq_create_with_socket(uint32_t count, size_t obj_size, int socket_id, unsigned int flags) { if (bbq_check_power_of_two(count) == false || count == 1) { - BBQ_ERR_LOG("bbq entries number must be power of two and greater than 1, now is :%lu", count); + BBQ_ERR_LOG("bbq entries number must be power of two and greater than 1, now is :%u", count); return NULL; } @@ -229,13 +327,13 @@ bbq_queue_s* bbq_ring_create_with_socket(uint32_t count, size_t obj_size, int so } /* 创建消息队列,count必须大于1,且是2的N次幂,bn和bs将根据count值自动计算,free_func先设置NULL */ -bbq_queue_s* bbq_ring_create(uint32_t count, size_t obj_size, unsigned int flags) { +struct bbq_s *bbq_create(uint32_t count, size_t obj_size, unsigned int flags) { // 传入无效socket_id,将使用malloc分配内存 - return bbq_ring_create_with_socket(count, obj_size, BBQ_INVALID_SOCKET, flags); + return bbq_create_with_socket(count, obj_size, BBQ_INVALID_SOCKET, flags); } /* 释放消息队列,与bbq_ring_create系列接口成对*/ -void bbq_ring_free(bbq_queue_s* q) { +void bbq_ring_free(struct bbq_s *q) { if (q == NULL) { return; } @@ -252,271 +350,62 @@ void bbq_ring_free(bbq_queue_s* q) { #define BBQ_F_SINGLE 0x0 #define BBQ_F_ARRAY_1D 0x1 #define BBQ_F_ARRAY_2D 0x2 -void commit_entry(bbq_queue_s* q, bbq_entry_desc_s* e, void* data, uint32_t flag) { +void commit_entry(struct bbq_s *q, struct bbq_entry_desc_s *e, void const *data, uint32_t flag) { size_t idx = e->off * q->entry_size; if (BBQ_COPY_POINTER(q->flags)) { // 指针入队列 switch (flag) { - case BBQ_F_ARRAY_1D: - char* tmp = (char*)data; - char* entry = &(e->block->entries[idx]); - for (size_t i = 0; i < e->actual_burst; i++) { - memcpy(entry, &tmp, q->entry_size); - entry += q->entry_size; - tmp += q->obj_size; - } - break; - case BBQ_F_ARRAY_2D: - case BBQ_F_SINGLE: - // 二维数组名等于首成员的地址,这里data其实是void **data, &data等同于 &(data[0]) - memcpy(&(e->block->entries[idx]), data, q->entry_size * e->actual_burst); - - void** tmp3 = (void**)(e->block->entries); - uint16_t* tmp2 = (uint16_t*)(tmp3[0]); - break; - default: - break; + case BBQ_F_ARRAY_1D: { + char *tmp = (char *)data; + char *entry = &(e->block->entries[idx]); + for (size_t i = 0; i < e->actual_burst; i++) { + memcpy(entry, &tmp, q->entry_size); + entry += q->entry_size; + tmp += q->obj_size; + } + break; + } + case BBQ_F_ARRAY_2D: + case BBQ_F_SINGLE: + // 二维数组名等于首成员的地址,这里data其实是void **data, &data等同于 &(data[0]) + memcpy(&(e->block->entries[idx]), data, q->entry_size * e->actual_burst); + break; + default: + break; } } else { // 数据入队列 switch (flag) { - case BBQ_F_ARRAY_1D: - case BBQ_F_SINGLE: - memcpy(&(e->block->entries[idx]), data, q->entry_size * e->actual_burst); - break; - case BBQ_F_ARRAY_2D: - void** tmp = (void**)data; - char* entry = &(e->block->entries[idx]); - for (size_t i = 0; i < e->actual_burst; i++) { - memcpy(entry, *tmp, q->entry_size); - entry += q->entry_size; - tmp++; - } - break; - default: - break; - } - } - atomic_fetch_add(&e->block->committed, e->actual_burst); -} - -/* 消息队列入队 */ -static struct bbq_status __bbq_enqueue(bbq_queue_s* q, void* data, uint32_t n, uint32_t flag) { - struct bbq_status ret = {.status = 0, .actual_burst = 0}; - - if (q == NULL || data == NULL) { - ret.status = BBQ_NULL_PTR; - return ret; - } - - while (true) { - // 获取当前phead,转为索引后获取到当前的blk - uint64_t ph = atomic_load(&q->phead); - bbq_block_s* blk = &(q->blocks[bbq_idx(q, ph)]); - bbq_queue_state_s state = allocate_entry(q, blk, n); - - switch (state.state) { - case BBQ_ALLOCATED: - commit_entry(q, &state.e, data, flag); - ret.actual_burst = state.e.actual_burst; - ret.status = BBQ_OK; - return ret; - case BBQ_BLOCK_DONE: - bbq_queue_state_e pstate = advance_phead(q, ph); - switch (pstate) { - case BBQ_NO_ENTRY: - ret.status = BBQ_QUEUE_FULL; - return ret; - case BBQ_NOT_AVAILABLE: - ret.status = BBQ_QUEUE_BUSY; - return ret; - case BBQ_SUCCESS: - continue; - } - break; - default: - BBQ_DBG_LOG("Invalid QueueState in bbq_enqueue: %d", state.state); - ret.status = BBQ_ERROR; - return ret; - } - } -} - -int bbq_enqueue(bbq_queue_s* q, void* data) { - struct bbq_status ret = __bbq_enqueue(q, data, 1, BBQ_F_SINGLE); - return ret.status; -} - -/* 消息队列出队 */ -static struct bbq_status __bbq_dequeue(bbq_queue_s* q, void* deq_data, uint32_t n, uint32_t flag) { - struct bbq_status ret = {.status = 0, .actual_burst = 0}; - if (q == NULL || deq_data == NULL) { - ret.status = BBQ_NULL_PTR; - return ret; - } - - while (true) { - uint64_t ch = atomic_load(&q->chead); - bbq_block_s* blk = &(q->blocks[bbq_idx(q, ch)]); - - bbq_queue_state_s state; - state = reserve_entry(q, blk, n); - - switch (state.state) { - case BBQ_RESERVED: - if (consume_entry(q, &state.e, deq_data, flag)) { - ret.status = BBQ_OK; - ret.actual_burst = state.e.actual_burst; - return ret; - } else { - continue; - } - case BBQ_NO_ENTRY: - ret.status = BBQ_QUEUE_EMPTY; - return ret; - case BBQ_NOT_AVAILABLE: - ret.status = BBQ_QUEUE_BUSY; - return ret; - case BBQ_BLOCK_DONE: - if (advance_chead(q, ch, state.vsn)) { - continue; - } else { - ret.status = BBQ_QUEUE_EMPTY; - return ret; - } - default: - BBQ_DBG_LOG("Invalid QueueState in dequeue state: %d", state.state); - ret.status = BBQ_ERROR; - return ret; - } - } -} - -int bbq_dequeue(bbq_queue_s* q, void* deq_data) { - struct bbq_status ret = __bbq_dequeue(q, deq_data, 1, BBQ_F_SINGLE); - return ret.status; -} - -uint32_t bbq_max_burst(bbq_queue_s* q, uint32_t n) { - uint32_t burst = n; - if (burst > q->bs) { - burst = q->bs; - } - - return burst; -} - -uint32_t bbq_dequeue_burst_one_dimensional(bbq_queue_s* q, void* obj_table, uint32_t n) { - if (q == NULL || obj_table == NULL) { - return BBQ_NULL_PTR; - } - - uint32_t burst = 0; - uint32_t ready = 0; - void* obj = obj_table; - struct bbq_status ret = {0}; - - while (ready < n) { - burst = bbq_max_burst(q, n - ready); - ret = __bbq_dequeue(q, obj, burst, BBQ_F_ARRAY_1D); - if (ret.status != BBQ_OK) { + case BBQ_F_ARRAY_1D: + case BBQ_F_SINGLE: + memcpy(&(e->block->entries[idx]), data, q->entry_size * e->actual_burst); break; - } - obj += q->obj_size * ret.actual_burst; - ready += ret.actual_burst; - - // bbq_struct_print(q); - } - - return ready; -} - -uint32_t bbq_dequeue_burst_two_dimensional(bbq_queue_s* q, void** obj_table, uint32_t n) { - if (q == NULL || obj_table == NULL) { - return BBQ_NULL_PTR; - } - - uint32_t burst = 0; - uint32_t ready = 0; - void** obj_table_tmp = obj_table; - struct bbq_status ret = {0}; - - while (ready < n) { - burst = bbq_max_burst(q, n - ready); - ret = __bbq_dequeue(q, obj_table_tmp, burst, BBQ_F_ARRAY_2D); - if (ret.status != BBQ_OK) { + case BBQ_F_ARRAY_2D: { + void **tmp = (void **)data; + char *entry = &(e->block->entries[idx]); + for (size_t i = 0; i < e->actual_burst; i++) { + memcpy(entry, *tmp, q->entry_size); + entry += q->entry_size; + tmp++; + } break; } - obj_table_tmp += ret.actual_burst; - ready += ret.actual_burst; - - // bbq_struct_print(q); - } - - return ready; -} - -/* 尝试一次入队多个数据,直到达到最大数量,或是入队失败 */ -uint32_t bbq_enqueue_burst_one_dimensional(bbq_queue_s* q, void* obj_table, uint32_t n) { - if (q == NULL || obj_table == NULL) { - return BBQ_NULL_PTR; - } - - uint32_t burst = 0; - uint32_t ready = 0; - void* obj = obj_table; - struct bbq_status ret = {0}; - - while (ready < n) { - burst = bbq_max_burst(q, n - ready); - ret = __bbq_enqueue(q, obj, burst, BBQ_F_ARRAY_1D); - if (ret.status != BBQ_OK) { + default: break; } - obj += q->obj_size * ret.actual_burst; - ready += ret.actual_burst; - - // bbq_struct_print(q); } - - return ready; -} - -/* 尝试一次入队多个数据,直到达到最大数量,或是入队失败 */ -uint32_t bbq_enqueue_burst_two_dimensional(bbq_queue_s* q, void** obj_table, uint32_t n) { - if (q == NULL || obj_table == NULL) { - return BBQ_NULL_PTR; - } - - uint32_t burst = 0; - uint32_t ready = 0; - void** obj_table_tmp = obj_table; - struct bbq_status ret = {0}; - - while (ready < n) { - burst = bbq_max_burst(q, n - ready); - ret = __bbq_enqueue(q, obj_table_tmp, burst, BBQ_F_ARRAY_2D); - if (ret.status != BBQ_OK) { - break; - } - obj_table_tmp += ret.actual_burst; - ready += ret.actual_burst; - - // bbq_struct_print(q); - } - - return ready; + atomic_fetch_add(&e->block->committed, e->actual_burst); } -bbq_queue_state_s allocate_entry(bbq_queue_s* q, bbq_block_s* block, uint32_t n) { - bbq_queue_state_s state = {0}; +struct bbq_queue_state_s allocate_entry(struct bbq_s *q, struct bbq_block_s *block, uint32_t n) { + struct bbq_queue_state_s state = {0}; if (bbq_off(q, atomic_load(&block->allocated)) >= q->bs) { state.state = BBQ_BLOCK_DONE; return state; } - uint64_t old = atomic_fetch_add(&block->allocated, n); // burst + uint64_t old = atomic_fetch_add(&block->allocated, n); uint64_t committed_vsn = bbq_cur_vsn(q, atomic_load(&block->committed)); // committed_vsn在当前块被初始化后值是不变的,通过比较vsn值,来判断allocated的off是否溢出了,导致vsn+1 @@ -542,18 +431,22 @@ bbq_queue_state_s allocate_entry(bbq_queue_s* q, bbq_block_s* block, uint32_t n) return state; } -bbq_queue_state_e advance_phead(bbq_queue_s* q, uint64_t ph) { +enum bbq_queue_state_e advance_phead(struct bbq_s *q, uint64_t ph) { // 获取下一个block - bbq_block_s* n_blk; - n_blk = &(q->blocks[(bbq_idx(q, ph) + 1) & q->idx_mask]); + uint64_t cur = 0; + struct bbq_block_s *n_blk = &(q->blocks[(bbq_idx(q, ph) + 1) & q->idx_mask]); + uint64_t ph_vsn = bbq_head_vsn(q, ph); - uint64_t cur, reserved; if (BBQ_POLIC_RETRY_NEW(q->flags)) { cur = atomic_load(&n_blk->consumed); - if (bbq_cur_vsn(q, cur) < bbq_head_vsn(q, ph) || // 生产者赶上了消费者 - (bbq_cur_vsn(q, cur) == bbq_head_vsn(q, ph) && bbq_off(q, cur) != q->bs)) { + uint64_t reserved; + uint64_t consumed_off = bbq_off(q, cur); + uint64_t consumed_vsn = bbq_cur_vsn(q, cur); + + if (consumed_vsn < ph_vsn || // 生产者赶上了消费者 + (consumed_vsn == ph_vsn && consumed_off != q->bs)) { reserved = atomic_load(&n_blk->reserved); - if (bbq_off(q, reserved) == bbq_off(q, cur)) { + if (bbq_off(q, reserved) == consumed_off) { return BBQ_NO_ENTRY; } else { return BBQ_NOT_AVAILABLE; @@ -562,22 +455,73 @@ bbq_queue_state_e advance_phead(bbq_queue_s* q, uint64_t ph) { } else { cur = atomic_load(&n_blk->committed); // 生产者避免前进到上一轮中尚未完全提交的区块 - if (bbq_cur_vsn(q, cur) == bbq_head_vsn(q, ph) && bbq_off(q, cur) != q->bs) { + if (bbq_cur_vsn(q, cur) == ph_vsn && bbq_off(q, cur) != q->bs) { return BBQ_NOT_AVAILABLE; } } // 用head的version初始化下一个块,version在高位,version+1,idex/offset清零,如果没有被其他线程执行过,数值会高于旧值。多线程同时只更新一次。 - fetch_max(&n_blk->committed, set_cur_vsn(q, bbq_head_vsn(q, ph) + 1)); - fetch_max(&n_blk->allocated, set_cur_vsn(q, bbq_head_vsn(q, ph) + 1)); + uint64_t new_vsn = set_cur_vsn(q, ph_vsn + 1); + fetch_max(&n_blk->committed, new_vsn); + fetch_max(&n_blk->allocated, new_vsn); // 索引+1,当超过索引范围,也就是循环下一轮块时,version+1 fetch_max(&q->phead, ph + 1); return BBQ_SUCCESS; } +/* 消息队列入队 */ +static struct bbq_status __bbq_enqueue(struct bbq_s *q, void const *data, uint32_t n, uint32_t flag) { + struct bbq_status ret = {.status = 0, .actual_burst = 0}; + + if (q == NULL || data == NULL) { + ret.status = BBQ_NULL_PTR; + return ret; + } + + while (true) { + // 获取当前phead,转为索引后获取到当前的blk + uint64_t ph = atomic_load(&q->phead); + struct bbq_block_s *blk = &(q->blocks[bbq_idx(q, ph)]); + struct bbq_queue_state_s state = allocate_entry(q, blk, n); + + switch (state.state) { + case BBQ_ALLOCATED: + commit_entry(q, &state.e, data, flag); + ret.actual_burst = state.e.actual_burst; + ret.status = BBQ_OK; + return ret; + case BBQ_BLOCK_DONE: { + enum bbq_queue_state_e pstate = advance_phead(q, ph); + switch (pstate) { + case BBQ_NO_ENTRY: + ret.status = BBQ_QUEUE_FULL; + return ret; + case BBQ_NOT_AVAILABLE: + ret.status = BBQ_QUEUE_BUSY; + return ret; + case BBQ_SUCCESS: + continue; + default: + ret.status = BBQ_ERROR; + return ret; + } + break; + } + default: + ret.status = BBQ_ERROR; + return ret; + } + } +} + +int bbq_enqueue(struct bbq_s *q, void *data) { + struct bbq_status ret = __bbq_enqueue(q, data, 1, BBQ_F_SINGLE); + return ret.status; +} + /* 更新成功 reserve成功的个数 */ -uint32_t reserve_update(bbq_cursor* aotmic, uint64_t reserved, uint32_t n) { +uint32_t reserve_update(bbq_cursor *aotmic, uint64_t reserved, uint32_t n) { if (n == 1) { // fetch_max返回的是旧值,如果旧值等于局部变量reserved,则代表数据由当前线程更新 if (fetch_max(aotmic, reserved + 1) == reserved) { @@ -591,9 +535,9 @@ uint32_t reserve_update(bbq_cursor* aotmic, uint64_t reserved, uint32_t n) { } } -bbq_queue_state_s reserve_entry(bbq_queue_s* q, bbq_block_s* block, uint32_t n) { +struct bbq_queue_state_s reserve_entry(struct bbq_s *q, struct bbq_block_s *block, uint32_t n) { while (true) { - bbq_queue_state_s state; + struct bbq_queue_state_s state; uint64_t reserved = atomic_load(&block->reserved); uint64_t reserved_off = bbq_off(q, reserved); uint64_t reserved_svn = bbq_cur_vsn(q, reserved); @@ -609,7 +553,7 @@ bbq_queue_state_s reserve_entry(bbq_queue_s* q, bbq_block_s* block, uint32_t n) uint64_t committed = atomic_load(&block->committed); uint64_t committed_off = bbq_off(q, committed); - if (committed_off == reserved_off) { // TODO:多entry关注 + if (committed_off == reserved_off) { // TODO:多entry关注 state.state = BBQ_NO_ENTRY; return state; } @@ -623,9 +567,9 @@ bbq_queue_state_s reserve_entry(bbq_queue_s* q, bbq_block_s* block, uint32_t n) } } - int32_t tmp = committed_off - reserved_off; + uint32_t tmp = committed_off - reserved_off; uint32_t reserved_cnt = reserve_update(&block->reserved, reserved, tmp < n ? tmp : n); - if (reserved_cnt > 0) { // TODO:多entry时关注 + if (reserved_cnt > 0) { // TODO:多entry时关注 state.state = BBQ_RESERVED; state.e.actual_burst = reserved_cnt; state.e.block = block; @@ -645,36 +589,37 @@ bbq_queue_state_s reserve_entry(bbq_queue_s* q, bbq_block_s* block, uint32_t n) } } -bool consume_entry(bbq_queue_s* q, bbq_entry_desc_s* e, void* deq_data, uint32_t flag) { +bool consume_entry(struct bbq_s *q, struct bbq_entry_desc_s *e, void *deq_data, uint32_t flag) { size_t idx = e->off * q->entry_size; if (BBQ_COPY_POINTER(q->flags)) { switch (flag) { - case BBQ_F_ARRAY_2D: - case BBQ_F_SINGLE: - memcpy(deq_data, &(e->block->entries[idx]), q->entry_size * e->actual_burst); - break; - case BBQ_F_ARRAY_1D: - default: - break; + case BBQ_F_ARRAY_2D: + case BBQ_F_SINGLE: + memcpy(deq_data, &(e->block->entries[idx]), q->entry_size * e->actual_burst); + break; + case BBQ_F_ARRAY_1D: + default: + break; } } else { switch (flag) { - case BBQ_F_ARRAY_1D: - case BBQ_F_SINGLE: - memcpy(deq_data, &(e->block->entries[idx]), q->entry_size * e->actual_burst); - break; - case BBQ_F_ARRAY_2D: - void** tmp = (void**)deq_data; - char* entry = &(e->block->entries[idx]); - for (size_t i = 0; i < e->actual_burst; i++) { - memcpy(*tmp, entry, q->entry_size); - entry += q->entry_size; - tmp++; - } - break; - default: - break; + case BBQ_F_ARRAY_1D: + case BBQ_F_SINGLE: + memcpy(deq_data, &(e->block->entries[idx]), q->entry_size * e->actual_burst); + break; + case BBQ_F_ARRAY_2D: { + void **tmp = (void **)deq_data; + char *entry = &(e->block->entries[idx]); + for (size_t i = 0; i < e->actual_burst; i++) { + memcpy(*tmp, entry, q->entry_size); + entry += q->entry_size; + tmp++; + } + break; + } + default: + break; } } @@ -682,6 +627,7 @@ bool consume_entry(bbq_queue_s* q, bbq_entry_desc_s* e, void* deq_data, uint32_t if (BBQ_POLIC_RETRY_NEW(q->flags)) { atomic_fetch_add(&e->block->consumed, e->actual_burst); } else { + // TODO:优化,考虑allocated vsn溢出?考虑判断如果生产满了,直接移动head? allocated = atomic_load(&e->block->allocated); // 预留的entry所在的块,已经被新生产的数据赶上了 if (bbq_cur_vsn(q, allocated) != e->vsn) { @@ -692,95 +638,207 @@ bool consume_entry(bbq_queue_s* q, bbq_entry_desc_s* e, void* deq_data, uint32_t return true; } -bool advance_chead(bbq_queue_s* q, uint64_t ch, uint64_t ver) { - bbq_block_s* n_blk = &(q->blocks[(bbq_idx(q, ch) + 1) & q->idx_mask]); +bool advance_chead(struct bbq_s *q, uint64_t ch, uint64_t ver) { + uint64_t ch_idx = bbq_idx(q, ch); + struct bbq_block_s *n_blk = &(q->blocks[(ch_idx + 1) & q->idx_mask]); + uint64_t ch_vsn = bbq_head_vsn(q, ch); uint64_t committed = atomic_load(&n_blk->committed); + uint64_t committed_vsn = bbq_cur_vsn(q, committed); if (BBQ_POLIC_RETRY_NEW(q->flags)) { - if (bbq_cur_vsn(q, committed) != bbq_head_vsn(q, ch) + 1) { + if (committed_vsn != ch_vsn + 1) { // 消费者追上了生产者,下一块还未开始生产 return false; } - fetch_max(&n_blk->consumed, set_cur_vsn(q, bbq_head_vsn(q, ch) + 1)); - fetch_max(&n_blk->reserved, set_cur_vsn(q, bbq_head_vsn(q, ch) + 1)); + uint64_t new_vsn = set_cur_vsn(q, ch_vsn + 1); + fetch_max(&n_blk->consumed, new_vsn); + fetch_max(&n_blk->reserved, new_vsn); } else { // 通过检查下一个块的版本是否大于或等于当前块来保证 FIFO 顺序. - // 第一个块是一个特殊情况,因为与其他块相比,它的版本总是相差一个。因此,如果 ch.bbq_idx == 0,我们在比较中加 1 - if (bbq_cur_vsn(q, committed) < ver + (bbq_idx(q, ch) == 0)) + // 第一个块是一个特殊情况,因为与其他块相比,它的版本总是相差一个。因此,如果 ch_idx == 0,我们在比较中加 1 + if (committed_vsn < ver + (ch_idx == 0)) return false; - fetch_max(&n_blk->reserved, set_cur_vsn(q, bbq_cur_vsn(q, committed))); + fetch_max(&n_blk->reserved, set_cur_vsn(q, committed_vsn)); } fetch_max(&q->chead, ch + 1); return true; } -inline uint64_t bbq_idx(bbq_queue_s* q, uint64_t x) { - return x & q->idx_mask; -} +/* 消息队列出队 */ +static struct bbq_status __bbq_dequeue(struct bbq_s *q, void *deq_data, uint32_t n, uint32_t flag) { + struct bbq_status ret = {.status = 0, .actual_burst = 0}; + if (q == NULL || deq_data == NULL) { + ret.status = BBQ_NULL_PTR; + return ret; + } -inline uint64_t bbq_off(bbq_queue_s* q, uint64_t x) { - return x & q->off_mask; -} + while (true) { + uint64_t ch = atomic_load(&q->chead); + struct bbq_block_s *blk = &(q->blocks[bbq_idx(q, ch)]); -inline uint64_t bbq_head_vsn(bbq_queue_s* q, uint64_t x) { - return x >> q->idx_bits; + struct bbq_queue_state_s state; + state = reserve_entry(q, blk, n); + + switch (state.state) { + case BBQ_RESERVED: + if (consume_entry(q, &state.e, deq_data, flag)) { + ret.status = BBQ_OK; + ret.actual_burst = state.e.actual_burst; + return ret; + } else { + continue; + } + case BBQ_NO_ENTRY: + ret.status = BBQ_QUEUE_EMPTY; + return ret; + case BBQ_NOT_AVAILABLE: + ret.status = BBQ_QUEUE_BUSY; + return ret; + case BBQ_BLOCK_DONE: + if (advance_chead(q, ch, state.vsn)) { + continue; + } else { + ret.status = BBQ_QUEUE_EMPTY; + return ret; + } + default: + ret.status = BBQ_ERROR; + return ret; + } + } } -inline uint64_t bbq_cur_vsn(bbq_queue_s* q, uint64_t x) { - return x >> q->off_bits; +int bbq_dequeue(struct bbq_s *q, void *deq_data) { + struct bbq_status ret = __bbq_dequeue(q, deq_data, 1, BBQ_F_SINGLE); + return ret.status; } -inline uint64_t set_cur_vsn(bbq_queue_s* q, uint64_t ver) { - return ver << q->off_bits; +uint32_t bbq_max_burst(struct bbq_s *q, uint32_t n) { + uint32_t burst = n; + if (burst > q->bs) { + burst = q->bs; + } + + return burst; } -void* bbq_memset(void* data, size_t size) { - if (data != NULL && size > 0) { - memset(data, 0, size); +static uint32_t bbq_dequeue_burst_one_dimensional(struct bbq_s *q, void *obj_table, uint32_t n) { + if (q == NULL || obj_table == NULL) { + return BBQ_NULL_PTR; + } + + uint32_t burst = 0; + uint32_t ready = 0; + void *obj = obj_table; + struct bbq_status ret = {0}; + + while (ready < n) { + burst = bbq_max_burst(q, n - ready); + ret = __bbq_dequeue(q, obj, burst, BBQ_F_ARRAY_1D); + if (ret.status != BBQ_OK) { + break; + } + obj += q->obj_size * ret.actual_burst; + ready += ret.actual_burst; } + + return ready; } -#ifdef BBQ_MEMORY -typedef struct { - aotmic_uint64 malloc_cnt; - aotmic_uint64 malloc_size; - aotmic_uint64 free_cnt; - aotmic_uint64 free_size; -} bbq_memory_s; -bbq_memory_s bbq_memory_g[BBQ_MODULE_MAX] = {0}; -#endif +static uint32_t bbq_dequeue_burst_two_dimensional(struct bbq_s *q, void **obj_table, uint32_t n) { + if (q == NULL || obj_table == NULL) { + return BBQ_NULL_PTR; + } -void* bbq_malloc(bbq_module_e module, int socket_id, size_t size) { - void* ptr = NULL; - if (socket_id >= 0) { - ptr = numa_alloc_onnode(size, 0); - } else { - ptr = malloc(size); + uint32_t burst = 0; + uint32_t ready = 0; + void **obj_table_tmp = obj_table; + struct bbq_status ret = {0}; + + while (ready < n) { + burst = bbq_max_burst(q, n - ready); + ret = __bbq_dequeue(q, obj_table_tmp, burst, BBQ_F_ARRAY_2D); + if (ret.status != BBQ_OK) { + break; + } + obj_table_tmp += ret.actual_burst; + ready += ret.actual_burst; } -#ifdef BBQ_MEMORY - if (ptr != NULL) { - atomic_fetch_add(&bbq_memory_g[module].malloc_cnt, 1); - atomic_fetch_add(&bbq_memory_g[module].malloc_size, size); + + return ready; +} + +/* 尝试一次入队多个数据,直到达到最大数量,或是入队失败 */ +uint32_t bbq_enqueue_burst_one_dimensional(struct bbq_s *q, void const *obj_table, uint32_t n) { + if (q == NULL || obj_table == NULL) { + return BBQ_NULL_PTR; } -#endif - return ptr; + uint32_t burst = 0; + uint32_t ready = 0; + void const *obj = obj_table; + struct bbq_status ret = {0}; + + while (ready < n) { + burst = bbq_max_burst(q, n - ready); + ret = __bbq_enqueue(q, obj, burst, BBQ_F_ARRAY_1D); + if (ret.status != BBQ_OK) { + break; + } + obj += q->obj_size * ret.actual_burst; + ready += ret.actual_burst; + } + + return ready; } -void bbq_free(bbq_module_e module, int socket_id, void* ptr, size_t size) { -#ifdef BBQ_MEMORY - if (ptr != NULL) { - atomic_fetch_add(&bbq_memory_g[module].free_cnt, 1); - atomic_fetch_add(&bbq_memory_g[module].free_size, size); +/* 尝试一次入队多个数据,直到达到最大数量,或是入队失败 */ +uint32_t bbq_enqueue_burst_two_dimensional(struct bbq_s *q, void *const *obj_table, uint32_t n) { + if (q == NULL || obj_table == NULL) { + return BBQ_NULL_PTR; } -#endif - // free(ptr); - if (socket_id >= 0) { - numa_free(ptr, size); - } else { - free(ptr); + + uint32_t burst = 0; + uint32_t ready = 0; + void *const *obj_table_tmp = obj_table; + struct bbq_status ret = {0}; + + while (ready < n) { + burst = bbq_max_burst(q, n - ready); + ret = __bbq_enqueue(q, obj_table_tmp, burst, BBQ_F_ARRAY_2D); + if (ret.status != BBQ_OK) { + break; + } + obj_table_tmp += ret.actual_burst; + ready += ret.actual_burst; } + + return ready; +} + +uint32_t bbq_enqueue_burst_value(struct bbq_s *q, void const *obj_table, uint32_t n) { + return bbq_enqueue_burst_one_dimensional(q, obj_table, n); +} + +uint32_t bbq_enqueue_burst_value_two_dimensional(struct bbq_s *q, void *const *obj_table, uint32_t n) { + return bbq_enqueue_burst_two_dimensional(q, obj_table, n); +} + +uint32_t bbq_enqueue_burst_ptr(struct bbq_s *q, void *const *obj_table, uint32_t n) { + return bbq_enqueue_burst_two_dimensional(q, obj_table, n); +} + +uint32_t bbq_enqueue_burst_ptr_one_dimensional(struct bbq_s *q, void const *obj_table, uint32_t n) { + return bbq_enqueue_burst_one_dimensional(q, obj_table, n); +} + +uint32_t bbq_dequeue_burst_ptr(struct bbq_s *q, void **obj_table, uint32_t n) { + return bbq_dequeue_burst_two_dimensional(q, obj_table, n); +} + +uint32_t bbq_dequeue_burst_value(struct bbq_s *q, void *obj_table, uint32_t n) { + return bbq_dequeue_burst_one_dimensional(q, obj_table, n); } bool bbq_malloc_free_equal() { @@ -807,23 +865,25 @@ bool bbq_malloc_free_equal() { #endif } -bool bbq_check_array_bounds(bbq_queue_s* q) { +bool bbq_check_array_bounds(struct bbq_s *q) { #ifdef BBQ_MEMORY - void* value = malloc(q->entry_size); + void *value = malloc(q->entry_size); memset(value, BBQ_MEM_MAGIC, q->entry_size); for (size_t i = 0; i < q->bn; i++) { // 针对内存检查版本,申请了bs+1个entry - char* last_entry = q->blocks[i].entries + q->bs * q->entry_size; + char *last_entry = q->blocks[i].entries + q->bs * q->entry_size; if (memcmp(last_entry, value, q->entry_size) != 0) { return false; } } +#else + AVOID_WARNING(q); #endif return true; } -void bbq_memory_info() { +void bbq_memory_print() { #ifdef BBQ_MEMORY for (int i = 0; i < BBQ_MODULE_MAX; i++) { uint64_t malloc_cnt = atomic_load(&bbq_memory_g[i].malloc_cnt); @@ -832,21 +892,22 @@ void bbq_memory_info() { continue; } - BBQ_INFO_LOG("[%d]bbq malloc:%lu free:%lu", i, - atomic_load(&bbq_memory_g[i].malloc_cnt), - atomic_load(&bbq_memory_g[i].free_cnt)); + printf("[%d]bbq malloc:%lu free:%lu\n", i, + atomic_load(&bbq_memory_g[i].malloc_cnt), + atomic_load(&bbq_memory_g[i].free_cnt)); } if (bbq_malloc_free_equal()) { - BBQ_INFO_LOG("all memory free"); + printf("all memory free\n"); } else { BBQ_ERR_LOG("memory not all free"); } #endif } -#ifdef BBQ_DEBUG -void bbq_block_print(bbq_queue_s* q, bbq_block_s* block) { +#if 1 +// 调试用 +void bbq_block_print(struct bbq_s *q, struct bbq_block_s *block) { bbq_cursor allocated = atomic_load(&block->allocated); bbq_cursor committed = atomic_load(&block->committed); bbq_cursor reserved = atomic_load(&block->reserved); @@ -857,11 +918,12 @@ void bbq_block_print(bbq_queue_s* q, bbq_block_s* block) { printf(" consumed:%lu\n\n", bbq_off(q, consumed)); } -void bbq_struct_print(bbq_queue_s* q) { +void bbq_struct_print(struct bbq_s *q) { + printf("-------------\n"); printf("ph idx:%lu vsn:%lu\n", bbq_idx(q, q->phead), bbq_head_vsn(q, q->phead)); bbq_block_print(q, &(q->blocks[bbq_idx(q, q->phead)])); - // printf("ch idx:%lu vsn:%lu", bbq_idx(q, q->chead), bbq_head_vsn(q, q->chead)); - // bbq_block_print(q, &(q->blocks[bbq_idx(q, q->chead)])); + printf("ch idx:%lu vsn:%lu", bbq_idx(q, q->chead), bbq_head_vsn(q, q->chead)); + bbq_block_print(q, &(q->blocks[bbq_idx(q, q->chead)])); } #endif
\ No newline at end of file diff --git a/bbq/test.c b/bbq/test.c new file mode 100644 index 0000000..7fa8ecf --- /dev/null +++ b/bbq/test.c @@ -0,0 +1,54 @@ +/* + * @Description: 描述信息 + * @Date: 2024-06-13 21:45:38 + * @LastEditTime: 2024-06-17 18:28:18 + */ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// 假设我们有一些uint16_t的指针,并且我们想要复制它们的地址 +void copy_pointer_array(void **dest, uint16_t **src, size_t num_pointers) { + // 使用memcpy复制指针数组的内容 + memcpy(dest, src, num_pointers * sizeof(uint16_t *)); +} + +// 一个简单的函数来展示如何使用这些指针 +void print_through_pointers(void *entries, size_t num_pointers) { + uint16_t **pointers = (uint16_t **)entries; + for (size_t i = 0; i < num_pointers; ++i) { + if (pointers[i]) { + printf("Pointer %zu points to %p, value: %u\n", i, (void *)pointers[i], *pointers[i]); + } else { + printf("Pointer %zu is NULL\n", i); + } + } +} + +struct test_s { + void *entries; +}; + +int main() { + // 示例:创建一些uint16_t的指针和值 + uint16_t val1 = 123, val2 = 456, val3 = 789; + uint16_t *ptrs[3] = {&val1, &val2, &val3}; + + printf("%p\n", ptrs[0]); + printf("%p\n", ptrs[1]); + printf("%p\n", ptrs[2]); + + // 使用void指针进行复制 + struct test_s tt; + tt.entries = malloc(3 * sizeof(uint16_t *)); + copy_pointer_array(tt.entries, (uint16_t **)ptrs, 3); + + // 通过void指针读取数据 + print_through_pointers(tt.entries, 3); + + // 清理内存 + free(tt.entries); + + return 0; +}
\ No newline at end of file diff --git a/bbq/tests/common/test_mix.c b/bbq/tests/common/test_mix.c index 1009c81..bcadaa5 100644 --- a/bbq/tests/common/test_mix.c +++ b/bbq/tests/common/test_mix.c @@ -1,7 +1,7 @@ /* * @Description: 描述信息 * @Date: 2024-05-25 10:55:48 - * @LastEditTime: 2024-06-07 16:54:45 + * @LastEditTime: 2024-06-17 17:14:16 */ #define _GNU_SOURCE #include "test_mix.h" @@ -26,13 +26,6 @@ void *test_malloc(test_module_e module, size_t size) { return ptr; } -void *test_calloc(test_module_e module, size_t size) { - void *ptr = test_malloc(module, size); - if (ptr != NULL) { - memset(ptr, 0, size); - } -} - void test_free(test_module_e module, void *ptr) { if (ptr != NULL) { atomic_fetch_add(&test_memory_g[module].free_cnt, 1); @@ -46,7 +39,7 @@ bool test_malloc_free_equal() { 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) { - BBQ_ERR_LOG("[module:%d] malloc:%lu free:%lu, test malloc-free not equal\n", i, 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; } } @@ -57,7 +50,7 @@ void test_memory_counter_clear() { memset(test_memory_g, 0, sizeof(test_memory_g)); } -void test_memory_info() { +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); @@ -65,23 +58,20 @@ void test_memory_info() { continue; } - BBQ_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)); + 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()) { - BBQ_INFO_LOG("all memory free"); + TEST_INFO_LOG("all memory free"); } else { - BBQ_ERR_LOG("memory not all free"); + TEST_ERR_LOG("memory not all free"); } } test_time_metric test_clock_time_get() { test_time_metric metric = {0}; - struct timespec timestamp; - - // clock_gettime(CLOCK_MONOTONIC, &metric.timestamp); //从系统启动这一刻起开始计时,不受系统时间被用户改变的影响 clock_gettime(CLOCK_REALTIME, &metric.timestamp); // 系统实时时间,随系统实时时间改变而改变 return metric; } @@ -164,48 +154,6 @@ char *test_ring_type_enum2str(test_ring_type ring_type) { } } -uint16_t **test_enqueue_table_create(uint32_t count) { - uint16_t **table = test_malloc(TEST_MODULE_TABLE, sizeof(uint16_t **) * count); - if (table == NULL) { - return NULL; - } - memset(table, 0, sizeof(uint16_t **) * count); - - for (uint32_t i = 0; i < count; i++) { - table[i] = test_malloc(TEST_MODULE_TABLE, sizeof(uint16_t)); - if (table[i] == NULL) { - goto error; - } - *table[i] = TEST_TABLE_DATA_MAGIC; - } - - return table; - -error: - if (table) { - for (uint32_t i = 0; i < count; i++) { - if (table[i] != NULL) { - test_free(TEST_MODULE_TABLE, table[i]); - } else { - break; - } - } - test_free(TEST_MODULE_TABLE, table); - } - return NULL; -} - -void test_enqueue_table_destory(uint16_t **table, uint32_t count) { - if (table == NULL) { - return; - } - - for (uint32_t i = 0; i < count; i++) { - test_free(TEST_MODULE_TABLE, table[i]); - } - test_free(TEST_MODULE_TABLE, table); -} - int test_setaffinity(int core_id) { cpu_set_t mask; CPU_ZERO(&mask); diff --git a/bbq/tests/common/test_mix.h b/bbq/tests/common/test_mix.h index 82b3d7f..d2299fe 100644 --- a/bbq/tests/common/test_mix.h +++ b/bbq/tests/common/test_mix.h @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-11 11:48:13 + * @LastEditTime: 2024-06-17 18:13:32 * @Email: [email protected] * @Describe: TODO */ @@ -18,8 +18,6 @@ #include <stdatomic.h> #endif -#define TEST_TABLE_DATA_MAGIC 12345 - typedef enum { TEST_THREAD_PRODUCER, TEST_THREAD_CONSUMER, @@ -110,6 +108,30 @@ typedef enum { 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); @@ -121,12 +143,63 @@ 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_calloc(test_module_e module, size_t size); extern void test_free(test_module_e module, void *ptr); -extern void test_memory_info(); +extern void test_memory_counter_print(); extern void test_memory_counter_clear(); extern bool test_malloc_free_equal(); -extern uint16_t **test_enqueue_table_create(uint32_t count); -extern void test_enqueue_table_destory(uint16_t **table, uint32_t count); extern int test_setaffinity(int core_id); + +#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 6b57df7..9a96e33 100644 --- a/bbq/tests/common/test_queue.c +++ b/bbq/tests/common/test_queue.c @@ -1,69 +1,68 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 23:25:09 + * @LastEditTime: 2024-06-18 04:11:12 * @Email: [email protected] * @Describe: TODO */ #include "test_queue.h" -#include <sys/prctl.h> -#include <unistd.h> #include "bbq.h" #include "test_mix.h" -extern bool bbq_check_array_bounds(bbq_queue_s* q); +#include <sys/prctl.h> +#include <unistd.h> +extern bool bbq_check_array_bounds(struct bbq_s *q); +extern struct bbq_s *bbq_ring_create_bnbs(uint32_t bn, uint32_t bs, size_t obj_size, unsigned int flags); +extern struct bbq_s *bbq_ring_create_bnbs_with_socket(uint32_t bn, uint32_t bs, size_t obj_size, int socket_id, unsigned int flags); -uint32_t test_bbq_enqueue_burst(void* ring, void* obj_table, uint32_t n, uint16_t thread_idx) { - return bbq_enqueue_burst_two_dimensional(ring, obj_table, n); +uint32_t test_bbq_enqueue_burst(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx) { + TEST_AVOID_WARNING(thread_idx); + return bbq_enqueue_burst_ptr(ring, obj_table, n); } -int test_queue_init_bbq(test_cfg* cfg, test_queue_s* q) { - bbq_queue_s* ring; +int test_queue_init_bbq(test_cfg *cfg, test_queue_s *q) { size_t obj_size = sizeof(test_data); if (cfg->ring.block_count == 0) { - q->ring = bbq_ring_create_with_socket(cfg->ring.entries_cnt, obj_size, 0, BBQ_F_POLICY_RETRY_NEW | BBQ_F_COPY_POINTER); + q->ring = bbq_create_with_socket(cfg->ring.entries_cnt, obj_size, 0, BBQ_CREATE_F_RETRY_NEW | BBQ_CREATE_F_COPY_PTR); } else { q->ring = bbq_ring_create_bnbs_with_socket(cfg->ring.block_count, cfg->ring.entries_cnt / cfg->ring.block_count, obj_size, - 0, BBQ_F_POLICY_RETRY_NEW | BBQ_F_COPY_POINTER); + 0, BBQ_CREATE_F_RETRY_NEW | BBQ_CREATE_F_COPY_PTR); } if (q->ring == NULL) { - BBQ_ERR_LOG("bbq create queue failed"); + TEST_ERR_LOG("bbq create queue failed"); return BBQ_NULL_PTR; } - bbq_queue_s* bbq_ring = (bbq_queue_s*)q->ring; - BBQ_DBG_LOG("block number:%lu size:%lu", bbq_ring->bn, bbq_ring->bs); - q->ring_free_f = (test_ring_free_f)bbq_ring_free; q->enqueue_f = (test_ring_enqueue_f)bbq_enqueue; q->dequeue_f = (test_ring_dequeue_f)bbq_dequeue; - q->dequeue_burst_f = (test_dequeue_burst_f)bbq_dequeue_burst_two_dimensional; + q->dequeue_burst_f = (test_dequeue_burst_f)bbq_dequeue_burst_ptr; q->enqueue_burst_f = (test_enqueue_burst_f)test_bbq_enqueue_burst; return 0; } -void test_queue_destory(test_queue_s* q) { +void test_queue_destory(test_queue_s *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) { +bool test_all_producer_exit(test_info_s *test_info) { return atomic_load(&test_info->ctl.producer_exit) == test_info->cfg.ring.producer_cnt; } -void test_wait_all_threads_ready(test_ctl* ctl) { +void test_wait_all_threads_ready(test_ctl *ctl) { pthread_barrier_wait(&ctl->all_threads_start); - BBQ_DBG_LOG("thread init done!"); + TEST_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)); +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)); if (exit_data == NULL) { - BBQ_ERR_LOG("malloc failed"); + TEST_ERR_LOG("malloc failed"); exit(-1); } @@ -72,7 +71,7 @@ test_exit_data* test_exit_data_create(test_thread_arg_s* t_arg) { exit_data->simple_data = test_data_create(size); if (exit_data->simple_data == NULL) { - BBQ_ERR_LOG("malloc failed"); + TEST_ERR_LOG("malloc failed"); exit(-1); } exit_data->arg = t_arg; @@ -83,14 +82,14 @@ test_exit_data* test_exit_data_create(test_thread_arg_s* t_arg) { return exit_data; } -test_exit_data* test_exit_data_destory(test_exit_data* 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); } -test_data** test_data_create(size_t cnt) { - test_data** simple_data = test_malloc(TEST_MODULE_DATA, sizeof(*simple_data) * cnt); +test_data **test_data_create(size_t cnt) { + test_data **simple_data = test_malloc(TEST_MODULE_DATA, sizeof(*simple_data) * cnt); test_time_metric enqueue_time = test_clock_time_get(); for (size_t i = 0; i < cnt; i++) { simple_data[i] = test_malloc(TEST_MODULE_DATA, sizeof(*simple_data[i])); @@ -101,42 +100,41 @@ test_data** test_data_create(size_t cnt) { return simple_data; } -void test_data_destory(test_data** data, size_t cnt) { +void test_data_destory(test_data **data, size_t cnt) { for (size_t i = 0; i < cnt; i++) { test_free(TEST_MODULE_DATA, data[i]); } test_free(TEST_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 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 enqueue_cnt = 0; test_time_metric op_use_start = test_clock_time_get(); - enqueue_cnt = q->enqueue_burst_f(q->ring, data, burst_cnt, thread_idx); + enqueue_cnt = q->enqueue_burst_f(q->ring, (void **)data, burst_cnt, thread_idx); *op_use_diff = test_clock_time_sub(test_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 test_exec_dequeue(test_queue_s *q, test_data **data, size_t burst_cnt, test_time_metric *op_use_diff) { uint32_t dequeue_cnt = 0; test_time_metric op_use_start = test_clock_time_get(); - dequeue_cnt = q->dequeue_burst_f(q->ring, (void**)data, burst_cnt); + dequeue_cnt = q->dequeue_burst_f(q->ring, (void **)data, burst_cnt); *op_use_diff = test_clock_time_sub(test_clock_time_get(), op_use_start); return dequeue_cnt; } -void* test_thread_producer_start(void* arg) { - int ret = 0; +void *test_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); + 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); char thread_name[128] = {0}; uint64_t op_ok_latency_ns = 0; @@ -144,10 +142,10 @@ void* test_thread_producer_start(void* arg) { uint64_t run_ok_times = cfg->run.run_ok_times / cfg->ring.producer_cnt; test_time_metric op_latency = {0}; - snprintf(thread_name, sizeof(thread_name), "producer:%x", exit_data->thread_id); + 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) { - BBQ_ERR_LOG("test_setaffinity error"); + TEST_ERR_LOG("test_setaffinity error"); exit(-1); } @@ -164,9 +162,9 @@ void* test_thread_producer_start(void* arg) { enqueue_cnt = test_exec_enqueue(q, exit_data->simple_data, cfg->ring.burst_cnt, &op_latency, t_arg->thread_idx); } else { // 由于rmind不支持指定个数的批量出队列,为了兼容它,这里分配的空间位置entries大小。 - test_data** data = test_data_create(cfg->ring.entries_cnt); + test_data **data = test_data_create(cfg->ring.entries_cnt); if (data == NULL) { - BBQ_ERR_LOG("malloc falied"); + TEST_ERR_LOG("malloc falied"); exit(-1); } enqueue_cnt = test_exec_enqueue(q, data, cfg->ring.burst_cnt, &op_latency, t_arg->thread_idx); @@ -195,31 +193,31 @@ void* test_thread_producer_start(void* arg) { exit_data->op_err_latency_ns = op_err_latency_ns; atomic_fetch_add(&test_info->ctl.producer_exit, 1); - BBQ_DBG_LOG("producer-----> en_ok:%lu", ok_cnt); + TEST_DBG_LOG("producer-----> en_ok:%lu", ok_cnt); pthread_exit(exit_data); } -void* test_thread_consumer_start(void* arg) { +void *test_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); + 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); uint64_t latency_ns = 0; test_time_metric op_latency = {0}; - uint64_t op_ok_latency_ns; + 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); + test_data **deq_data = test_malloc(TEST_MODULE_DATA, sizeof(*deq_data) * cfg->ring.entries_cnt); - snprintf(thread_name, sizeof(thread_name), "consumer:%x", exit_data->thread_id); + 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) { - BBQ_ERR_LOG("test_setaffinity error"); + TEST_ERR_LOG("test_setaffinity error"); exit(-1); } @@ -239,21 +237,21 @@ void* test_thread_consumer_start(void* arg) { deq_cnt = test_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]; + test_data *data = deq_data[i]; if (cfg->ring.workload == TEST_WORKLOAD_SIMPLE) { if (data->data != TEST_DATA_MAGIC) { - BBQ_ERR_LOG("the obtained data is not consistent with the expectation, expect:%u actual:%u", TEST_DATA_MAGIC, data->data); + TEST_ERR_LOG("the obtained data is not consistent with the expectation, expect:%u actual:%u", TEST_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)) { - BBQ_ERR_LOG("enqueue_time is 0"); + TEST_ERR_LOG("enqueue_time is 0"); exit(-1); } if (data->data != TEST_DATA_MAGIC) { - BBQ_ERR_LOG("the obtained data is not consistent with the expectation, expect:%u actual:%u", TEST_DATA_MAGIC, data->data); + TEST_ERR_LOG("the obtained data is not consistent with the expectation, expect:%u actual:%u", TEST_DATA_MAGIC, data->data); data_error_cnt += 1; } @@ -279,26 +277,24 @@ void* test_thread_consumer_start(void* arg) { exit_data->data_error_cnt = data_error_cnt; test_free(TEST_MODULE_DATA, deq_data); - BBQ_DBG_LOG("consumer-----> de_ok:%lu", ok_cnt); + TEST_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) { +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) { - BBQ_DBG_LOG("sleep %lus, and notify all threads to exit...", test_info->cfg.run.run_time); + 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; } for (uint32_t i = 0; i < thread_cnt; i++) { - pthread_join(threads[i], (void**)(&exit_data[i])); // 等待每个线程结束 + pthread_join(threads[i], (void **)(&exit_data[i])); // 等待每个线程结束 } } - -pthread_t* -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) { - BBQ_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 +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; arg->q = q; arg->ttype = ttype; @@ -317,14 +313,13 @@ test_one_thread_create(test_info_s* test_info, test_queue_s* q, test_thread_type 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 *test_threads_create(test_info_s *test_info, test_queue_s *q) { // 创建生产者消费者线程 - int ret; uint16_t thread_id = 0; int core_id = 0; - test_cfg* cfg = &test_info->cfg; + test_cfg *cfg = &test_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 *)test_malloc(TEST_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; @@ -337,7 +332,7 @@ pthread_t* test_threads_create(test_info_s* test_info, test_queue_s* q) { // SPMC,第一个核心给生产者,其他分配给消费者 test_one_thread_create(test_info, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); thread_id++; - for (int i = 0; i < cfg->ring.consumer_cnt; i++) { + 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])); thread_id++; @@ -346,15 +341,15 @@ pthread_t* test_threads_create(test_info_s* test_info, test_queue_s* q) { // MPSC,第一个核心给消费者,其他分配给生产者 test_one_thread_create(test_info, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); thread_id++; - for (int i = 0; i < cfg->ring.producer_cnt; i++) { + 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])); thread_id++; } } else { // MPMC 或 只有生产者 或这有消费者,核心交错分配 - uint32_t pcnt = cfg->ring.producer_cnt; // 生产者个数 - uint32_t ccnt = cfg->ring.consumer_cnt; // 消费者个数 + uint32_t pcnt = cfg->ring.producer_cnt; // 生产者个数 + uint32_t ccnt = cfg->ring.consumer_cnt; // 消费者个数 for (core_id = 0; core_id < cfg->base.cores_cnt && pcnt > 0 && ccnt > 0;) { if ((core_id & 1) == 0) { // 偶数 @@ -369,13 +364,13 @@ pthread_t* test_threads_create(test_info_s* test_info, test_queue_s* q) { CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); } - for (int i = 0; i < pcnt; i++) { + 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])); thread_id++; CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); } - for (int i = 0; i < ccnt; i++) { + 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])); thread_id++; CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); @@ -385,12 +380,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) { +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 test_merge_data_detail(test_merge_data* merge, test_exit_data* exit_data) { +void test_merge_data_detail(test_merge_data *merge, test_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; @@ -399,7 +394,7 @@ 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) { +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}; diff --git a/bbq/tests/common/test_queue.h b/bbq/tests/common/test_queue.h index 22bce92..723f0b3 100644 --- a/bbq/tests/common/test_queue.h +++ b/bbq/tests/common/test_queue.h @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 18:59:37 + * @LastEditTime: 2024-06-17 18:17:24 * @Email: [email protected] * @Describe: TODO */ @@ -10,12 +10,12 @@ #include "test_mix.h" #include <pthread.h> -#define TEST_DATA_MAGIC 1234567890 +#define TEST_DATA_MAGIC 0x1F // 为了兼容所有类型的数据,存储1字节大小的数据 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); +typedef uint32_t (*test_enqueue_burst_f)(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx); typedef uint32_t (*test_dequeue_burst_f)(void *ring, void **obj_table, uint32_t n); typedef bool (*test_ring_empty_f)(void *ring); @@ -79,22 +79,22 @@ typedef struct { 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 pthread_t *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_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 test_exit_data *test_exit_data_destory(test_exit_data *data); +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); -extern uint64_t bbq_idx(bbq_queue_s *q, uint64_t x); -extern uint64_t bbq_off(bbq_queue_s *q, uint64_t x); -extern uint64_t bbq_head_vsn(bbq_queue_s *q, uint64_t x); -extern uint64_t bbq_cur_vsn(bbq_queue_s *q, uint64_t x); +extern uint64_t bbq_idx(struct bbq_s *q, uint64_t x); +extern uint64_t bbq_off(struct bbq_s *q, uint64_t x); +extern uint64_t bbq_head_vsn(struct bbq_s *q, uint64_t x); +extern uint64_t bbq_cur_vsn(struct bbq_s *q, uint64_t x); extern test_data **test_data_create(size_t cnt); extern void test_data_destory(test_data **data, size_t cnt); #endif
\ No newline at end of file diff --git a/bbq/tests/unittest/ut.h b/bbq/tests/unittest/ut.h index b733c9f..b36c2ee 100644 --- a/bbq/tests/unittest/ut.h +++ b/bbq/tests/unittest/ut.h @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-05-31 17:33:50 + * @LastEditTime: 2024-06-14 15:56:17 * @Email: [email protected] * @Describe: TODO */ @@ -17,7 +17,7 @@ typedef struct { } testdata_s; typedef struct { - bbq_queue_s *q; + struct bbq_s *q; uint32_t usleep; // 该线程每次执行间隔睡眠时间 bool until_end; // 循环读取,直到队列空或满 uint64_t thread_exec_times; // 每个线程生产/消费次数 diff --git a/bbq/tests/unittest/ut_example.cc b/bbq/tests/unittest/ut_example.cc index 943aeb8..fe78e03 100644 --- a/bbq/tests/unittest/ut_example.cc +++ b/bbq/tests/unittest/ut_example.cc @@ -1,14 +1,8 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 23:28:23 + * @LastEditTime: 2024-06-18 15:11:23 * @Email: [email protected] - * @Describe: TODO - */ -/* - * @Author: liuyu - * @LastEditTime: 2024-06-04 18:16:51 - * @Email: [email protected] - * @Describe: 简单的测试用例,测试基本功能,同时让调用者快速上手 + * @Describe: 简单的测试用例,测试基本功能 */ #include "gtest/gtest.h" @@ -17,154 +11,403 @@ extern "C" { #include "test_queue.h" #include "ut.h" extern bool bbq_malloc_free_equal(); -extern void bbq_memory_info(); -extern bool bbq_check_array_bounds(bbq_queue_s* q); +extern void bbq_memory_print(); +extern bool bbq_check_array_bounds(struct bbq_s *q); +extern void bbq_struct_print(struct bbq_s *q); +extern uint32_t bbq_enqueue_burst_ptr_one_dimensional(struct bbq_s *q, void const *obj_table, uint32_t n); +extern uint32_t bbq_enqueue_burst_value_two_dimensional(struct bbq_s *q, void *const *obj_table, uint32_t n); } #define BUF_CNT 4096 -#define ENQ_TABLE1_CNT 4000 -#define ENQ_TABLE2_CNT 90 -#define ENQ_TABLE3_CNT 10 -TEST(burst, retry_new_cp_value) { - test_memory_counter_clear(); - uint32_t ret1 = 0; - uint32_t ret2 = 0; - uint32_t ret3 = 0; - bbq_queue_s* q; +class bbq_example : public testing::Test { + protected: + virtual void SetUp() override { + // 1.清空内存malloc/free统计 + test_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); + } + + virtual void TearDown() override { + // 1.释放测试数据 + TEST_DOUBLE_PTR_DATA_DESTORY(enq_table1, BUF_CNT); + TEST_PTR_ARRAY_DATA_DESTORY(enq_table2, BUF_CNT); + + // 2.内存泄漏检测 + EXPECT_TRUE(bbq_malloc_free_equal()); + EXPECT_TRUE(test_malloc_free_equal()); + } + + // 入队数据 + uint16_t **enq_table1; + uint16_t *enq_table2[BUF_CNT]; + uint16_t enq_table3[BUF_CNT]; +}; + +TEST_F(bbq_example, single_retry_new_cp_ptr) { + int ret = 0; + uint64_t cnt = 0; + uint16_t *deq_data = NULL; + + // 创建队列 + struct bbq_s *q = bbq_create(BUF_CNT, sizeof(uint16_t), BBQ_CREATE_F_RETRY_NEW | BBQ_CREATE_F_COPY_PTR); + EXPECT_TRUE(q); + + // 空队出队失败 + EXPECT_EQ(bbq_dequeue(q, &deq_data), BBQ_QUEUE_EMPTY); + + // 全部入队成功 + for (uint32_t i = 0; i < 4000; i++) { + if (bbq_enqueue(q, &enq_table1[i]) == 0) { + cnt++; + } + } - // 创建测试数据,3种数据类型,均将数据值入队列 - uint16_t** enq_table1 = test_enqueue_table_create(ENQ_TABLE1_CNT); - uint16_t* enq_table2[ENQ_TABLE2_CNT] = {0}; - for (int i = 0; i < ENQ_TABLE2_CNT; i++) { - enq_table2[i] = (uint16_t*)test_malloc(TEST_MODULE_DATA, sizeof(uint16_t)); - *enq_table2[i] = TEST_TABLE_DATA_MAGIC; + // 部分入队成功 + for (uint32_t i = 0; i < 4000; i++) { + if (bbq_enqueue(q, &enq_table2[i]) == 0) { + cnt++; + } } - uint16_t enq_table3[ENQ_TABLE3_CNT]; - for (int i = 0; i < ENQ_TABLE3_CNT; i++) { - enq_table3[i] = TEST_TABLE_DATA_MAGIC; + + // 入队成功个数等于队列总数 + EXPECT_EQ(cnt, BUF_CNT); + + cnt = 0; + for (uint32_t i = 0; i < BUF_CNT; i++) { + ret = bbq_dequeue(q, &deq_data); + if (ret == 0) { + EXPECT_EQ(*deq_data, TEST_DATA_MAGIC); + cnt++; + } } + // 全部出队成功 + EXPECT_EQ(cnt, BUF_CNT); + + // 空队出队失败 + EXPECT_EQ(bbq_dequeue(q, &deq_data), BBQ_QUEUE_EMPTY); +} - uint16_t deq_table1[ENQ_TABLE1_CNT] = {0}; - uint16_t* deq_table2 = (uint16_t*)test_malloc(TEST_MODULE_DATA, sizeof(uint16_t) * BUF_CNT); +TEST_F(bbq_example, single_retry_new_cp_value) { + int ret = 0; + uint64_t cnt = 0; + uint16_t deq_data; // 创建队列 - q = bbq_ring_create(BUF_CNT, sizeof(uint16_t), BBQ_F_POLICY_RETRY_NEW | BBQ_F_COPY_VALUE); + struct bbq_s *q = bbq_create(BUF_CNT, sizeof(uint16_t), BBQ_CREATE_F_RETRY_NEW | BBQ_CREATE_F_COPY_VALUE); EXPECT_TRUE(q); - // 批量入队(全成功) - ret1 = bbq_enqueue_burst_two_dimensional(q, (void**)enq_table1, ENQ_TABLE1_CNT); - EXPECT_EQ(ret1, ENQ_TABLE1_CNT); + // 空队出队失败 + EXPECT_EQ(bbq_dequeue(q, &deq_data), BBQ_QUEUE_EMPTY); + + // 全部入队成功 + for (uint32_t i = 0; i < 4000; i++) { + if (bbq_enqueue(q, enq_table1[i]) == 0) { + cnt++; + } + } + + // 部分入队成功 + for (uint32_t i = 0; i < 4000; i++) { + if (bbq_enqueue(q, enq_table2[i]) == 0) { + cnt++; + } + } + + // 入队成功个数等于队列总数 + EXPECT_EQ(cnt, BUF_CNT); + + cnt = 0; + for (uint32_t i = 0; i < BUF_CNT; i++) { + ret = bbq_dequeue(q, &deq_data); + if (ret == 0) { + EXPECT_EQ(deq_data, TEST_DATA_MAGIC); + cnt++; + } + } + // 全部出队成功 + EXPECT_EQ(cnt, BUF_CNT); - // 批量入队(全成功) - ret2 = bbq_enqueue_burst_two_dimensional(q, (void**)enq_table2, ENQ_TABLE2_CNT); - EXPECT_EQ(ret2, ENQ_TABLE2_CNT); + // 空队出队失败 + EXPECT_EQ(bbq_dequeue(q, &deq_data), BBQ_QUEUE_EMPTY); +} + +TEST_F(bbq_example, single_drop_old_cp_pointer) { + int ret = 0; + uint64_t cnt = 0; + uint16_t *deq_data = NULL; + uint64_t first_cnt = BUF_CNT; + uint64_t second_cnt = 1000; + + // 创建队列 + struct bbq_s *q = bbq_create(BUF_CNT, sizeof(uint16_t), BBQ_CREATE_F_DROP_OLD | BBQ_CREATE_F_COPY_PTR); + EXPECT_TRUE(q); + EXPECT_LT(second_cnt, q->bs * q->bn); + + // 空队出队失败 + EXPECT_EQ(bbq_dequeue(q, &deq_data), BBQ_QUEUE_EMPTY); + + // 全部入队成功,入队个数是BUF_CNT的整数倍,因此到了一个边界,刚好与消费者位置一致(套了loop圈) + uint32_t loop = 3; + for (uint32_t n = 0; n < loop; n++) { + for (uint32_t i = 0; i < first_cnt; i++) { + ret = bbq_enqueue(q, &enq_table1[i]); + if (ret == 0) { + cnt++; + } + } + } + EXPECT_EQ(cnt, first_cnt * loop); + + // 全部入队成功 + cnt = 0; + for (uint32_t i = 0; i < second_cnt; i++) { + if (bbq_enqueue(q, &enq_table2[i]) == 0) { + cnt++; + } + } + EXPECT_EQ(cnt, second_cnt); + + cnt = 0; + for (uint32_t i = 0; i < BUF_CNT; i++) { + ret = bbq_dequeue(q, &deq_data); + if (ret == 0) { + EXPECT_EQ(*deq_data, TEST_DATA_MAGIC); + cnt++; + } + } + + // 一旦生产者追上了消费者,之前未消费的,以及当前块的数据全都作废了。 + EXPECT_EQ(cnt, second_cnt - q->bs); + + // 空队出队失败 + EXPECT_EQ(bbq_dequeue(q, &deq_data), BBQ_QUEUE_EMPTY); +} + +TEST_F(bbq_example, single_drop_old_cp_value) { + int ret = 0; + uint64_t cnt = 0; + uint16_t deq_data; + uint64_t first_cnt = BUF_CNT; + uint64_t second_cnt = 1000; + + // 创建队列 + struct bbq_s *q = bbq_create(BUF_CNT, sizeof(uint16_t), BBQ_CREATE_F_DROP_OLD | BBQ_CREATE_F_COPY_VALUE); + EXPECT_TRUE(q); + EXPECT_LT(second_cnt, q->bs * q->bn); + + // 空队出队失败 + EXPECT_EQ(bbq_dequeue(q, &deq_data), BBQ_QUEUE_EMPTY); + + // 全部入队成功,入队个数是BUF_CNT的整数倍,因此到了一个边界,刚好与消费者位置一致(套了loop圈) + uint32_t loop = 3; + for (uint32_t n = 0; n < loop; n++) { + for (uint32_t i = 0; i < first_cnt; i++) { + ret = bbq_enqueue(q, enq_table1[i]); + if (ret == 0) { + cnt++; + } + } + } + EXPECT_EQ(cnt, first_cnt * loop); + + // 全部入队成功 + cnt = 0; + for (uint32_t i = 0; i < second_cnt; i++) { + if (bbq_enqueue(q, enq_table2[i]) == 0) { + cnt++; + } + } + EXPECT_EQ(cnt, second_cnt); + + cnt = 0; + for (uint32_t i = 0; i < BUF_CNT; i++) { + ret = bbq_dequeue(q, &deq_data); + if (ret == 0) { + EXPECT_EQ(deq_data, TEST_DATA_MAGIC); + cnt++; + } + } + + // 一旦生产者追上了消费者,之前未消费的,以及当前块的数据全都作废了。 + EXPECT_EQ(cnt, second_cnt - q->bs); + + // 空队出队失败 + EXPECT_EQ(bbq_dequeue(q, &deq_data), BBQ_QUEUE_EMPTY); +} + +TEST_F(bbq_example, burst_retry_new_cp_value) { + struct bbq_s *q; + uint32_t ret1 = 0; + uint32_t ret2 = 0; + 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); + + // 创建队列 + q = bbq_create(BUF_CNT, sizeof(uint16_t), BBQ_CREATE_F_RETRY_NEW | BBQ_CREATE_F_COPY_VALUE); + EXPECT_TRUE(q); + EXPECT_LT(first_cnt, q->bn * q->bs); + + // 批量入队(全部成功) + // 推荐的函数,传入的数组地址连续,内部可以memcpy批量拷贝,速度快 + ret1 = bbq_enqueue_burst_value(q, (void const *)enq_table3, first_cnt); + EXPECT_EQ(ret1, first_cnt); // 批量入队(部分成功) - ret3 = bbq_enqueue_burst_one_dimensional(q, (void*)enq_table3, ENQ_TABLE3_CNT); - EXPECT_EQ(ret3, BUF_CNT - ret1 - ret2); + // 不推荐,但可用于特殊场景。由于需要将最终的值入队列,二维数组里的值不连续,需要循环赋值。 + ret2 = bbq_enqueue_burst_value_two_dimensional(q, (void *const *)enq_table2, second_cnt); + EXPECT_EQ(ret2, BUF_CNT - ret1); - /*------------------------------------------------------------------*/ - // 出队列(全成功) - ret1 = bbq_dequeue_burst_one_dimensional(q, (void*)deq_table1, ENQ_TABLE1_CNT); - EXPECT_EQ(ret1, ENQ_TABLE1_CNT); + // 出队列(全部成功) + ret1 = bbq_dequeue_burst_value(q, (void *)deq_table1, first_cnt); + EXPECT_EQ(ret1, first_cnt); // 出队列(部分成功) - ret2 = bbq_dequeue_burst_one_dimensional(q, (void*)deq_table2, BUF_CNT); + ret2 = bbq_dequeue_burst_value(q, (void *)deq_table2, second_cnt); EXPECT_EQ(ret2, BUF_CNT - ret1); // 验证数据 for (uint32_t i = 0; i < ret1; i++) { - EXPECT_EQ(deq_table1[i], TEST_TABLE_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(deq_table1[i], TEST_DATA_MAGIC) << "i :" << i; } for (uint32_t i = 0; i < ret2; i++) { - EXPECT_EQ(deq_table2[i], TEST_TABLE_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(deq_table2[i], TEST_DATA_MAGIC) << "i :" << i; } + EXPECT_TRUE(bbq_check_array_bounds(q)); bbq_ring_free(q); - - // 释放测试数据 - test_enqueue_table_destory(enq_table1, ENQ_TABLE1_CNT); - for (int i = 0; i < ENQ_TABLE2_CNT; i++) { - test_free(TEST_MODULE_DATA, enq_table2[i]); - } test_free(TEST_MODULE_DATA, deq_table2); - // 内存泄漏检测 - EXPECT_TRUE(bbq_malloc_free_equal()); - EXPECT_TRUE(test_malloc_free_equal()); } -TEST(burst, retry_new_cp_pointer) { - test_memory_counter_clear(); +TEST_F(bbq_example, burst_retry_new_cp_pointer) { + struct bbq_s *q; uint32_t ret1 = 0; uint32_t ret2 = 0; - uint32_t ret3 = 0; - bbq_queue_s* q; - - // 创建测试数据,3种数据类型,均将数据值入队列 - uint16_t** enq_table1 = test_enqueue_table_create(ENQ_TABLE1_CNT); - uint16_t* enq_table2[ENQ_TABLE2_CNT] = {0}; - for (int i = 0; i < ENQ_TABLE2_CNT; i++) { - enq_table2[i] = (uint16_t*)test_malloc(TEST_MODULE_DATA, sizeof(uint16_t)); - *enq_table2[i] = TEST_TABLE_DATA_MAGIC; - } - uint16_t enq_table3[ENQ_TABLE3_CNT]; - for (int i = 0; i < ENQ_TABLE3_CNT; i++) { - enq_table3[i] = TEST_TABLE_DATA_MAGIC; - } + uint64_t first_cnt = 4000; + uint64_t second_cnt = 1000; - uint16_t* deq_table1[BUF_CNT] = {0}; - uint16_t* deq_table2[BUF_CNT] = {0}; - uint16_t** deq_table3 = (uint16_t**)malloc(sizeof(uint16_t*) * BUF_CNT); + uint16_t *deq_table1[BUF_CNT] = {0}; + uint16_t **deq_table2 = (uint16_t **)test_malloc(TEST_MODULE_DATA, sizeof(uint16_t *) * BUF_CNT); // 创建队列 - q = bbq_ring_create(BUF_CNT, sizeof(uint16_t), BBQ_F_POLICY_RETRY_NEW | BBQ_F_COPY_POINTER); + q = bbq_create(BUF_CNT, sizeof(uint16_t), BBQ_CREATE_F_RETRY_NEW | BBQ_CREATE_F_COPY_PTR); EXPECT_TRUE(q); + EXPECT_LT(first_cnt, q->bn * q->bs); - ret1 = bbq_enqueue_burst_two_dimensional(q, (void**)enq_table1, ENQ_TABLE1_CNT); - EXPECT_EQ(ret1, ENQ_TABLE1_CNT); + // 批量入队(全部成功) + // 推荐的函数,传入的数组地址连续,内部可以memcpy批量拷贝,速度快 + ret1 = bbq_enqueue_burst_ptr(q, (void *const *)enq_table1, first_cnt); + EXPECT_EQ(ret1, first_cnt); - ret2 = bbq_enqueue_burst_two_dimensional(q, (void**)enq_table2, ENQ_TABLE2_CNT); - EXPECT_EQ(ret2, ENQ_TABLE2_CNT); - - ret3 = bbq_enqueue_burst_one_dimensional(q, (void*)enq_table3, ENQ_TABLE3_CNT); - EXPECT_EQ(ret3, BUF_CNT - ret1 - ret2); - - /*------------------------------------------------------------------*/ - ret1 = bbq_dequeue_burst_two_dimensional(q, (void**)deq_table1, ENQ_TABLE1_CNT); - EXPECT_EQ(ret1, ENQ_TABLE1_CNT); + // 批量入队(部分成功) + // 不推荐,但可用于特殊场景。将数组成员的每个地址入队,需要循环取成员地址。 + ret2 = bbq_enqueue_burst_ptr_one_dimensional(q, (const void *)enq_table3, second_cnt); + EXPECT_EQ(ret2, BUF_CNT - ret1); - ret2 = bbq_dequeue_burst_two_dimensional(q, (void**)deq_table2, ENQ_TABLE2_CNT); - EXPECT_EQ(ret2, ENQ_TABLE2_CNT); + // 出队列(全部成功) + ret1 = bbq_dequeue_burst_ptr(q, (void **)deq_table1, first_cnt); + EXPECT_EQ(ret1, first_cnt); - ret3 = bbq_dequeue_burst_two_dimensional(q, (void**)deq_table3, ENQ_TABLE3_CNT); - EXPECT_EQ(ret3, BUF_CNT - ret1 - ret2); + // 出队列(部分成功) + ret2 = bbq_dequeue_burst_ptr(q, (void **)deq_table2, second_cnt); + EXPECT_EQ(ret2, BUF_CNT - ret1); // 验证数据 for (uint32_t i = 0; i < ret1; i++) { - EXPECT_TRUE(deq_table1[i]); - EXPECT_EQ(*deq_table1[i], TEST_TABLE_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(*deq_table1[i], TEST_DATA_MAGIC) << "i :" << i; } for (uint32_t i = 0; i < ret2; i++) { - EXPECT_TRUE(deq_table2[i]); - EXPECT_EQ(*deq_table2[i], TEST_TABLE_DATA_MAGIC) << "i :" << i; + EXPECT_EQ(*deq_table2[i], TEST_DATA_MAGIC) << "i :" << i; } - for (uint32_t i = 0; i < ret3; i++) { - EXPECT_TRUE(deq_table3[i]); - EXPECT_EQ(*deq_table3[i], TEST_TABLE_DATA_MAGIC) << "i :" << i; + EXPECT_TRUE(bbq_check_array_bounds(q)); + bbq_ring_free(q); + test_free(TEST_MODULE_DATA, deq_table2); +} + +TEST_F(bbq_example, burst_drop_old_cp_pointer) { + struct bbq_s *q; + uint32_t ret1 = 0; + uint32_t ret2 = 0; + uint64_t first_cnt = BUF_CNT; + 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); + + // 创建队列 + q = bbq_create(BUF_CNT, sizeof(uint16_t), BBQ_CREATE_F_DROP_OLD | BBQ_CREATE_F_COPY_PTR); + EXPECT_TRUE(q); + EXPECT_LT(second_cnt, q->bs * q->bn); + + // 批量入队(全部成功) + // 推荐的函数,传入的数组地址连续,内部可以memcpy批量拷贝,速度快 + ret1 = bbq_enqueue_burst_ptr(q, (void *const *)enq_table1, first_cnt); + EXPECT_EQ(ret1, first_cnt); + + // 批量入队(全部成功),覆盖了旧数据 + // 不推荐,但可用于特殊场景。将数组成员的每个地址入队,需要循环取成员地址。 + ret2 = bbq_enqueue_burst_ptr_one_dimensional(q, (const void *)enq_table3, second_cnt); + EXPECT_EQ(ret2, second_cnt); + + // 出队列(部分成功) + // 一旦生产者追上了消费者,之前未消费的,以及当前块的数据全都作废了。 + ret1 = bbq_dequeue_burst_ptr(q, (void **)deq_table1, BUF_CNT); + EXPECT_EQ(ret1, second_cnt - q->bs); + + // 验证数据 + for (uint32_t i = 0; i < ret1; i++) { + EXPECT_EQ(*deq_table1[i], TEST_DATA_MAGIC) << "i :" << i; } + EXPECT_TRUE(bbq_check_array_bounds(q)); bbq_ring_free(q); + test_free(TEST_MODULE_DATA, deq_table2); +} - // 释放测试数据 - test_enqueue_table_destory(enq_table1, ENQ_TABLE1_CNT); - for (int i = 0; i < ENQ_TABLE2_CNT; i++) { - test_free(TEST_MODULE_DATA, enq_table2[i]); +TEST_F(bbq_example, burst_drop_old_cp_value) { + struct bbq_s *q; + uint32_t ret1 = 0; + uint32_t ret2 = 0; + uint64_t first_cnt = BUF_CNT; + uint64_t second_cnt = 1000; + + uint16_t deq_table1[BUF_CNT] = {0}; + + // 创建队列 + q = bbq_create(BUF_CNT, sizeof(uint16_t), BBQ_CREATE_F_DROP_OLD | BBQ_CREATE_F_COPY_VALUE); + EXPECT_TRUE(q); + EXPECT_LT(second_cnt, q->bs * q->bn); + + // 批量入队(全部成功) + // 推荐的函数,传入的数组地址连续,内部可以memcpy批量拷贝,速度快 + ret1 = bbq_enqueue_burst_value(q, (void const *)enq_table3, first_cnt); + EXPECT_EQ(ret1, first_cnt); + + // 批量入队(全部成功),覆盖了旧数据 + // 不推荐,但可用于特殊场景。将数组成员的每个地址入队,需要循环取成员地址。 + ret2 = bbq_enqueue_burst_value_two_dimensional(q, (void *const *)enq_table1, second_cnt); + EXPECT_EQ(ret2, second_cnt); + + // 出队列(部分成功) + // 一旦生产者追上了消费者,之前未消费的,以及当前块的数据全都作废了。 + ret1 = bbq_dequeue_burst_value(q, (void *)deq_table1, BUF_CNT); + EXPECT_EQ(ret1, second_cnt - q->bs); + + // 验证数据 + for (uint32_t i = 0; i < ret1; i++) { + EXPECT_EQ(deq_table1[i], TEST_DATA_MAGIC) << "i :" << i; } - // 内存泄漏检测 - EXPECT_TRUE(bbq_malloc_free_equal()); - EXPECT_TRUE(test_malloc_free_equal()); + + EXPECT_TRUE(bbq_check_array_bounds(q)); + bbq_ring_free(q); }
\ No newline at end of file diff --git a/bbq/tests/unittest/ut_head_cursor.cc b/bbq/tests/unittest/ut_head_cursor.cc index 6f6a42c..dd95e7e 100644 --- a/bbq/tests/unittest/ut_head_cursor.cc +++ b/bbq/tests/unittest/ut_head_cursor.cc @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 23:26:11 + * @LastEditTime: 2024-06-17 11:15:19 * @Email: [email protected] * @Describe: TODO */ @@ -9,51 +9,66 @@ extern "C" { #include "test_queue.h" #include "ut.h" extern bool bbq_malloc_free_equal(); -extern void bbq_memory_info(); -bool bbq_check_array_bounds(bbq_queue_s* q); +extern void bbq_memory_print(); +extern bool bbq_check_array_bounds(struct bbq_s *q); +extern struct bbq_s *bbq_ring_create_bnbs(uint32_t bn, uint32_t bs, size_t obj_size, unsigned int flags); +extern struct bbq_s *bbq_ring_create_bnbs_with_socket(uint32_t bn, uint32_t bs, size_t obj_size, int socket_id, unsigned int flags); } -void expect_phead(bbq_queue_s* q, uint64_t idx, uint64_t vsn, int line) { +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(bbq_malloc_free_equal()); + EXPECT_TRUE(test_malloc_free_equal()); + } +}; + +void expect_phead(struct bbq_s *q, uint64_t idx, uint64_t vsn, int line) { EXPECT_EQ(bbq_idx(q, q->phead), idx) << "line: " << line; EXPECT_EQ(bbq_head_vsn(q, q->phead), vsn) << "line: " << line; } -void expect_chead(bbq_queue_s* q, uint64_t idx, uint64_t vsn, int line) { +void expect_chead(struct bbq_s *q, uint64_t idx, uint64_t vsn, int line) { EXPECT_EQ(bbq_idx(q, q->chead), idx) << "line: " << line; EXPECT_EQ(bbq_head_vsn(q, q->chead), vsn) << "line: " << line; } -void expect_eq_allocated(bbq_queue_s* q, bbq_block_s* block, uint64_t off, uint64_t vsn, int line) { +void expect_eq_allocated(struct bbq_s *q, bbq_block_s *block, uint64_t off, uint64_t vsn, int line) { EXPECT_EQ(bbq_off(q, block->allocated), off) << "line: " << line; EXPECT_EQ(bbq_cur_vsn(q, block->allocated), vsn) << "line: " << line; } -void expect_eq_committed(bbq_queue_s* q, bbq_block_s* block, uint64_t off, uint64_t vsn, int line) { +void expect_eq_committed(struct bbq_s *q, bbq_block_s *block, uint64_t off, uint64_t vsn, int line) { EXPECT_EQ(bbq_off(q, block->committed), off) << "line: " << line; EXPECT_EQ(bbq_cur_vsn(q, block->committed), vsn) << "line: " << line; } -void expect_eq_consumed(bbq_queue_s* q, bbq_block_s* block, uint64_t off, uint64_t vsn, int line) { +void expect_eq_consumed(struct bbq_s *q, bbq_block_s *block, uint64_t off, uint64_t vsn, int line) { EXPECT_EQ(bbq_off(q, block->consumed), off) << "line: " << line; EXPECT_EQ(bbq_cur_vsn(q, block->consumed), vsn) << "line: " << line; } -void expect_eq_reserved(bbq_queue_s* q, bbq_block_s* block, uint64_t off, uint64_t vsn, int line) { +void expect_eq_reserved(struct bbq_s *q, bbq_block_s *block, uint64_t off, uint64_t vsn, int line) { EXPECT_EQ(bbq_off(q, block->reserved), off) << "line: " << line; EXPECT_EQ(bbq_cur_vsn(q, block->reserved), vsn) << "line: " << line; } // 初始化状态 -TEST(head_cursor, init) { +TEST_F(bbq_head_cursor, init) { test_memory_counter_clear(); - int ret = 0; - bbq_queue_s* q; + struct bbq_s *q; uint32_t bn = 2; uint32_t bs = 4; - int enqueue_data = TEST_DATA_MAGIC; - - q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_F_COPY_VALUE | BBQ_F_POLICY_RETRY_NEW); + q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_CREATE_F_COPY_VALUE | BBQ_CREATE_F_RETRY_NEW); EXPECT_TRUE(q); // 1.初始化状态,除了第一个block外其他块的4个游标都指向最后一个条目 @@ -78,7 +93,7 @@ TEST(head_cursor, init) { void ut_produce_something(uint32_t produce_cnt) { int ret = 0; - bbq_queue_s* q; + struct bbq_s *q; uint32_t bn = 8; uint32_t bs = 4096; int enqueue_data = TEST_DATA_MAGIC; @@ -87,7 +102,7 @@ void ut_produce_something(uint32_t produce_cnt) { EXPECT_GT(produce_cnt, 0); EXPECT_LE(produce_cnt, bs); - q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_F_COPY_VALUE | BBQ_F_POLICY_RETRY_NEW); + q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_CREATE_F_COPY_VALUE | BBQ_CREATE_F_RETRY_NEW); EXPECT_TRUE(q); // 生产produce_cnt @@ -127,7 +142,7 @@ void ut_produce_something(uint32_t produce_cnt) { bbq_ring_free(q); } // 在第一块内生产,然后被消费完 -TEST(head_cursor, produce_something) { +TEST_F(bbq_head_cursor, produce_something) { test_memory_counter_clear(); ut_produce_something(1); @@ -140,7 +155,7 @@ TEST(head_cursor, produce_something) { void ut_produce_next_block(uint32_t over) { int ret = 0; - bbq_queue_s* q; + struct bbq_s *q; uint32_t bn = 8; uint32_t bs = 4096; uint32_t produce_cnt = bs + over; @@ -150,7 +165,7 @@ void ut_produce_next_block(uint32_t over) { EXPECT_GT(over, 0); EXPECT_LT(over, bs); - q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_F_COPY_VALUE | BBQ_F_POLICY_RETRY_NEW); + q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_CREATE_F_COPY_VALUE | BBQ_CREATE_F_RETRY_NEW); EXPECT_TRUE(q); // 生产至第二块的第一个entry @@ -195,7 +210,7 @@ void ut_produce_next_block(uint32_t over) { } // 第一块生产完毕,第二块生产了若干,然后被消费完 -TEST(head_cursor, produce_next_block) { +TEST_F(bbq_head_cursor, produce_next_block) { test_memory_counter_clear(); ut_produce_next_block(1); @@ -208,14 +223,14 @@ TEST(head_cursor, produce_next_block) { void ut_produce_all_loop(uint32_t loop) { int ret = 0; - bbq_queue_s* q; + struct bbq_s *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_ring_create_bnbs(bn, bs, sizeof(int), BBQ_F_COPY_VALUE | BBQ_F_POLICY_RETRY_NEW); + q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_CREATE_F_COPY_VALUE | BBQ_CREATE_F_RETRY_NEW); EXPECT_TRUE(q); for (uint32_t cnt = 0; cnt < loop; cnt++) { @@ -253,7 +268,7 @@ void ut_produce_all_loop(uint32_t loop) { } // 完成多轮的满生产和满消费 -TEST(head_cursor, produce_all_loop) { +TEST_F(bbq_head_cursor, produce_all_loop) { test_memory_counter_clear(); ut_produce_all_loop(1); @@ -264,22 +279,20 @@ TEST(head_cursor, produce_all_loop) { EXPECT_TRUE(test_malloc_free_equal()); } -TEST(boundary, retry_new_full_empty) { +TEST_F(bbq_head_cursor, retry_new_full_empty) { test_memory_counter_clear(); int ret = 0; uint32_t entries_cnt = 4096; uint32_t loop = 1000; - bbq_queue_s* q; + struct bbq_s *q; - int* data = (int*)test_malloc(TEST_MODULE_UTEST, sizeof(*data) * entries_cnt); + int *data = (int *)test_malloc(TEST_MODULE_UTEST, sizeof(*data) * entries_cnt); int tmp_data = 0; EXPECT_TRUE(data); - q = bbq_ring_create(entries_cnt, sizeof(int), BBQ_F_COPY_VALUE | BBQ_F_POLICY_RETRY_NEW); + q = bbq_create(entries_cnt, sizeof(int), BBQ_CREATE_F_COPY_VALUE | BBQ_CREATE_F_RETRY_NEW); EXPECT_TRUE(q); - bool test = bbq_check_array_bounds(q); - for (uint32_t i = 0; i < loop; i++) { // 入满队 for (uint32_t j = 0; j < entries_cnt; j++) { @@ -333,12 +346,14 @@ TEST(boundary, retry_new_full_empty) { EXPECT_TRUE(test_malloc_free_equal()); } -TEST(boundary, mpsc_faa) { +TEST_F(bbq_head_cursor, mpsc_faa) { test_memory_counter_clear(); test_info_s test_info = { .cfg = { .base = { + .name = {}, + .introduce = {}, .cores_cnt = 4, }, .ring = { @@ -351,10 +366,15 @@ TEST(boundary, mpsc_faa) { .burst_cnt = 1, }, .run = { + .run_ok_times = 0, .run_time = 5, }, }, - .ctl = {.running = true}, + .ctl = { + .running = true, + .all_threads_start = {}, + .producer_exit = {}, + }, }; // 队列初始化 @@ -364,18 +384,20 @@ TEST(boundary, mpsc_faa) { ASSERT_TRUE(ret == 0); // 创建线程 - pthread_t* threads = test_threads_create(&test_info, &q); + 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_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 = {0}; + 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); @@ -386,37 +408,22 @@ TEST(boundary, mpsc_faa) { } test_free(TEST_MODULE_UTEST, exit_data); test_threads_destory(&test_info, threads); - EXPECT_TRUE(bbq_check_array_bounds((bbq_queue_s*)q.ring)); + EXPECT_TRUE(bbq_check_array_bounds((struct bbq_s *)q.ring)); test_queue_destory(&q); EXPECT_TRUE(bbq_malloc_free_equal()); EXPECT_TRUE(test_malloc_free_equal()); } -void debug_head_print(bbq_queue_s* q) { - printf("phead vsn:%d idx:%d\n", bbq_head_vsn(q, q->phead), bbq_idx(q, q->phead)); - printf("chead vsn:%d idx:%d\n", bbq_head_vsn(q, q->chead), bbq_idx(q, q->chead)); -} - -void debug_block_print(bbq_queue_s* q) { - for (int i = 0; i < q->bn; i++) { - printf("[%d]zzzz allocated:vsn:%d off:%d\n", i, bbq_cur_vsn(q, q->blocks[i].allocated.load()), bbq_off(q, q->blocks[i].allocated.load())); - printf("[%d]zzzz committed:%d off:%d\n", i, bbq_cur_vsn(q, q->blocks[i].committed.load()), bbq_off(q, q->blocks[i].committed.load())); - printf("[%d]zzzz reserved:%d off:%d\n", i, bbq_cur_vsn(q, q->blocks[i].reserved.load()), bbq_off(q, q->blocks[i].reserved.load())); - printf("[%d]zzzz consumed:%d off:%d\n\n", i, bbq_cur_vsn(q, q->blocks[i].consumed.load()), bbq_off(q, q->blocks[i].consumed.load())); - } -} - -TEST(boundary, drop_old_full_empty1) { +TEST_F(bbq_head_cursor, drop_old_full_empty1) { test_memory_counter_clear(); int ret = 0; uint32_t bn = 2; uint32_t bs = 4; - uint32_t over_cnt = 3; uint32_t loop = 1000; - bbq_queue_s* q; + struct bbq_s *q; int tmp_data = 0; - q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_F_COPY_VALUE | BBQ_F_POLICY_DROP_OLD); + q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_CREATE_F_COPY_VALUE | BBQ_CREATE_F_DROP_OLD); EXPECT_TRUE(q); for (uint32_t j = 0; j < loop; j++) { @@ -455,19 +462,19 @@ TEST(boundary, drop_old_full_empty1) { EXPECT_TRUE(test_malloc_free_equal()); } -TEST(boundary, drop_old_full_empty2) { +TEST_F(bbq_head_cursor, drop_old_full_empty2) { test_memory_counter_clear(); int ret = 0; uint32_t bn = 2; uint32_t bs = 4; uint32_t loop = 1000; uint32_t over_cnt = bs + 2; - bbq_queue_s* q; + struct bbq_s *q; EXPECT_EQ(over_cnt / bs, 1); int tmp_data = 0; - q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_F_COPY_VALUE | BBQ_F_POLICY_DROP_OLD); + q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_CREATE_F_COPY_VALUE | BBQ_CREATE_F_DROP_OLD); EXPECT_TRUE(q); // 入满队列,再入over_cnt diff --git a/bbq/tests/unittest/ut_mix.cc b/bbq/tests/unittest/ut_mix.cc index b279234..cb7c12a 100644 --- a/bbq/tests/unittest/ut_mix.cc +++ b/bbq/tests/unittest/ut_mix.cc @@ -1,22 +1,37 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 23:13:00 + * @LastEditTime: 2024-06-17 11:14:19 * @Email: [email protected] * @Describe: bbq除了队列操作外,其他函数的测试 */ #include "gtest/gtest.h" extern "C" { -#include <math.h> #include "test_mix.h" #include "ut.h" +#include <math.h> extern bool bbq_check_power_of_two(int n); extern uint32_t bbq_blocks_calc(uint32_t entries); extern unsigned ceil_log2(uint64_t x); -extern uint64_t fetch_max(aotmic_uint64* atom, uint64_t upd); +extern uint64_t fetch_max(aotmic_uint64 *atom, uint64_t upd); extern bool bbq_malloc_free_equal(); extern bool test_malloc_free_equal(); } -namespace { + +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(bbq_malloc_free_equal()); + EXPECT_TRUE(test_malloc_free_equal()); + } +}; typedef struct { uint64_t thread_cnt; @@ -24,43 +39,43 @@ typedef struct { aotmic_uint64 ready_thread_cnt; } ut_fetch_arg; -void* fetch_max_thread_func(void* arg) { - ut_fetch_arg* fetch_arg = (ut_fetch_arg*)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)); + uint64_t *ret = (uint64_t *)test_malloc(TEST_MODULE_UTEST, sizeof(*ret)); // 不同线程写入不同的>3的数 *ret = fetch_max(&fetch_arg->data, pthread_self() + 3); pthread_exit(ret); } -TEST(bbq_mix, fetch_max) { +TEST_F(bbq_mix, fetch_max) { test_memory_counter_clear(); uint64_t ret = 0; - ut_fetch_arg arg = {0}; - arg.data.store(1); // 初始化1 + ut_fetch_arg arg = {}; + arg.data.store(1); // 初始化1 arg.thread_cnt = 50; - ret = fetch_max(&arg.data, 2); // max比较后设置为2 + ret = fetch_max(&arg.data, 2); // max比较后设置为2 EXPECT_EQ(arg.data.load(), 2); EXPECT_EQ(ret, 1); - pthread_t* threads = (pthread_t*)test_malloc(TEST_MODULE_UTEST, sizeof(*threads) * arg.thread_cnt); + 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); + pthread_create(&threads[i], NULL, fetch_max_thread_func, (void *)&arg); } int eq_cnt = 0; - for (int i = 0; i < arg.thread_cnt; i++) { - uint64_t* tret; - pthread_join(threads[i], (void**)&tret); // 等待每个线程结束 + 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的个数 + eq_cnt++; // 统计返回2的个数 } test_free(TEST_MODULE_UTEST, tret); } @@ -71,7 +86,7 @@ TEST(bbq_mix, fetch_max) { EXPECT_TRUE(test_malloc_free_equal()); } -TEST(bbq_mix, power_of_two) { +TEST_F(bbq_mix, power_of_two) { test_memory_counter_clear(); uint32_t tmp = 0; @@ -83,7 +98,7 @@ TEST(bbq_mix, power_of_two) { for (uint32_t val = 5; val < max; val *= tmp) { EXPECT_FALSE(bbq_check_power_of_two(val)); if (val >= max / tmp) { - break; // 即将越界 + break; // 即将越界 } } @@ -98,7 +113,7 @@ TEST(bbq_mix, power_of_two) { EXPECT_TRUE(test_malloc_free_equal()); } -TEST(bbq_mix, bbq_blocks_calc) { +TEST_F(bbq_mix, bbq_blocks_calc) { test_memory_counter_clear(); uint32_t tmp = 0; @@ -121,7 +136,7 @@ TEST(bbq_mix, bbq_blocks_calc) { } else if (val <= 2147483648) { EXPECT_TRUE(bbq_blocks_calc(val) == 128); } else { - EXPECT_TRUE(0); // 异常 + EXPECT_TRUE(0); // 异常 } if (val >= max / tmp) { @@ -132,7 +147,7 @@ TEST(bbq_mix, bbq_blocks_calc) { EXPECT_TRUE(test_malloc_free_equal()); } -TEST(bbq_mix, ceil_log2) { +TEST_F(bbq_mix, ceil_log2) { test_memory_counter_clear(); uint32_t tmp = 0; @@ -149,4 +164,3 @@ TEST(bbq_mix, ceil_log2) { EXPECT_TRUE(bbq_malloc_free_equal()); EXPECT_TRUE(test_malloc_free_equal()); } -} // namespace
\ No newline at end of file diff --git a/bbq/tests/unittest/ut_data.cc b/bbq/tests/unittest/ut_multit.cc index 74ed0e2..8ab7276 100644 --- a/bbq/tests/unittest/ut_data.cc +++ b/bbq/tests/unittest/ut_multit.cc @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 23:25:39 + * @LastEditTime: 2024-06-17 11:07:02 * @Email: [email protected] * @Describe: TODO */ @@ -12,22 +12,38 @@ extern "C" { #include "ut.h" extern bool bbq_malloc_free_equal(); extern bool test_malloc_free_equal(); -extern void bbq_memory_info(); -bool bbq_check_array_bounds(bbq_queue_s* q); +extern void bbq_memory_print(); +bool bbq_check_array_bounds(struct bbq_s *q); } -TEST(data, correct) { - test_memory_counter_clear(); +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(bbq_malloc_free_equal()); + 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 = 1, - .consumer_cnt = 1, + .producer_cnt = 4, + .consumer_cnt = 4, .workload = TEST_WORKLOAD_SIMPLE, .entries_cnt = 4096, .block_count = 0, @@ -35,9 +51,14 @@ TEST(data, correct) { }, .run = { .run_ok_times = 50000, + .run_time = 0, }, }, - .ctl = {.running = true}, + .ctl = { + .running = true, + .all_threads_start = {}, + .producer_exit = {}, + }, }; // 队列初始化 @@ -47,16 +68,17 @@ TEST(data, correct) { ASSERT_TRUE(ret == 0); // 创建线程 - pthread_t* threads = test_threads_create(&test_info, &q); + 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_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 = {0}; + 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); @@ -67,8 +89,6 @@ TEST(data, correct) { } test_free(TEST_MODULE_UTEST, exit_data); test_threads_destory(&test_info, threads); - EXPECT_TRUE(bbq_check_array_bounds((bbq_queue_s*)q.ring)); + EXPECT_TRUE(bbq_check_array_bounds((struct bbq_s *)q.ring)); test_queue_destory(&q); - EXPECT_TRUE(bbq_malloc_free_equal()); - EXPECT_TRUE(test_malloc_free_equal()); } diff --git a/perf/CMakeLists.txt b/perf/CMakeLists.txt index a361c80..54801b1 100644 --- a/perf/CMakeLists.txt +++ b/perf/CMakeLists.txt @@ -10,12 +10,22 @@ include_directories( /home/admin/test/dpdk-23.07/build/install/include ) - # 将bbq单元测试里的公共文件,添加到perf里。 SET(TEST_COMMON_DIR ${PROJECT_SOURCE_DIR}/../bbq/tests/common) # 设置输出目录 -SET(OUTPUT_DIR ${PROJECT_SOURCE_DIR}/build/output) +if(NOT DEFINED OUTPUT_DIR) + # 如果没有被设置,则设置一个默认值 + SET(OUTPUT_DIR ${PROJECT_SOURCE_DIR}/build/output) +endif() + +# 设置编译类型,默认Release +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) +endif() + +add_compile_options(-Wall -Wextra) + # 库生成的路径 set(LIB_PATH ${OUTPUT_DIR}/lib) # 测试程序生成的路径 diff --git a/perf/benchmark/bcm_benchmark.c b/perf/benchmark/bcm_benchmark.c index 6cbbdfa..923fa1f 100644 --- a/perf/benchmark/bcm_benchmark.c +++ b/perf/benchmark/bcm_benchmark.c @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 16:32:40 + * @LastEditTime: 2024-06-14 17:34:15 * @Email: [email protected] * @Describe: TODO */ @@ -16,7 +16,7 @@ #include <sys/prctl.h> #include <unistd.h> -extern void bbq_memory_info(); +extern void bbq_memory_print(); extern bool bbq_malloc_free_equal(); 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) { @@ -24,17 +24,17 @@ void bcm_report_printf(test_cfg *cfg, test_merge_data *data, test_exit_data **ra double latency_ns = 0; double throughput = 0; - BBQ_COLOR_PRINT("\n---------%s---------", ttype == TEST_THREAD_PRODUCER ? "生产者" : "消费者"); + printf("\n---------%s---------\n", ttype == TEST_THREAD_PRODUCER ? "生产者" : "消费者"); double use_time = test_clock_time_to_double(&data->use_time); - BBQ_COLOR_PRINT("执行时间 : %lf 秒", use_time); - BBQ_COLOR_PRINT("执行次数 : %lu (burst=%u)", data->run_times, cfg->ring.burst_cnt); - BBQ_COLOR_PRINT("成功%s : %lu", ttype == TEST_THREAD_PRODUCER ? "入队" : "出队", data->ok_cnt); - BBQ_COLOR_PRINT("数据错误次数 : %lu", data->data_error_cnt); + 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("数据错误次数 : %lu\n", data->data_error_cnt); // 同时有生产者、消费者时才输出 if (cfg->ring.producer_cnt > 0 && cfg->ring.consumer_cnt > 0) { throughput = data->ok_cnt / use_time; - BBQ_COLOR_PRINT("吞吐 :%.0lf/s (%e/s)", throughput, throughput); + printf("吞吐 :%.0lf/s (%e/s)\n", throughput, throughput); // 多生产者单消费者 或 单生产者多消费才输出 if ((cfg->ring.producer_cnt == 1 && cfg->ring.consumer_cnt > 1) || @@ -43,7 +43,7 @@ void bcm_report_printf(test_cfg *cfg, test_merge_data *data, test_exit_data **ra 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); - BBQ_COLOR_PRINT(" %s-%d 吞吐 :%.0lf/s (%e/s)", name, bbq_idx, throughput, throughput); + printf(" %s-%d 吞吐 :%.0lf/s (%e/s)", name, bbq_idx, throughput, throughput); bbq_idx++; } } @@ -51,17 +51,17 @@ void bcm_report_printf(test_cfg *cfg, test_merge_data *data, test_exit_data **ra if (ttype == TEST_THREAD_CONSUMER && cfg->ring.workload == TEST_WORKLOAD_COMPLEX) { latency_ns = data->latency_ns * 1.0 / data->ok_cnt; - BBQ_COLOR_PRINT("数据延迟 :%.0lf 纳秒 (%e)", latency_ns, latency_ns); + printf("数据延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); } latency_ns = data->op_ok_latency_ns * 1.0 / data->ok_cnt; - BBQ_COLOR_PRINT("操作延迟 :%.0lf 纳秒 (%e)", latency_ns, latency_ns); + 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) { - BBQ_COLOR_PRINT("满队入队操作延迟 :%.0lf 纳秒 (%e)", latency_ns, latency_ns); + printf("满队入队操作延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); } else { - BBQ_COLOR_PRINT("空队出队操作延迟 :%.0lf 纳秒 (%e)", latency_ns, latency_ns); + printf("空队出队操作延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); } } } @@ -72,9 +72,9 @@ void bcm_report_generate(test_cfg *cfg, test_exit_data **exit_data, uint32_t thr test_merge_s merge = {0}; test_merge_all_data(exit_data, thread_cnt, &merge); - BBQ_COLOR_PRINT("ring类型: %s", test_ring_type_enum2str(cfg->ring.ring_type)); - BBQ_COLOR_PRINT("简介: %s", cfg->base.introduce); - BBQ_COLOR_PRINT("配置: %s", cfg->base.name); + printf("ring类型: %s\n", test_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); } @@ -84,7 +84,7 @@ void bcm_report_generate(test_cfg *cfg, test_exit_data **exit_data, uint32_t thr } if (cfg->ring.producer_cnt > 0 && cfg->ring.consumer_cnt > 0) { - BBQ_COLOR_PRINT("生产消费个数验证: %s", merge.consumer.ok_cnt == merge.producer.ok_cnt ? "相等" : "不等!!!!!!!!!"); + printf("生产消费个数验证: %s\n", merge.consumer.ok_cnt == merge.producer.ok_cnt ? "相等" : "不等!!!!!!!!!"); } } @@ -101,22 +101,20 @@ int main(int argc, char *argv[]) { burst_cnt = 1; } } else { - config = "/root/code/c/bbq-ly/perf/benchmark/config/compare/perf/perf_case2_simple_mpmc.ini"; - // ring_type = "rmind"; - // ring_type = "dpdk"; - ring_type = "bbq"; - burst_cnt = 1; - BBQ_ERR_LOG("use default config, ringt_type:%s burst:%u config:%s argc:%d", ring_type, burst_cnt, config, argc); + config = "/root/code/c/bbq-ly/perf/benchmark/config/compare/case1_simple_spsc.ini"; + ring_type = "rmind"; + burst_cnt = 16; + TEST_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}; - snprintf(thread_name, sizeof(thread_name), "main:%x", pthread_self()); + snprintf(thread_name, sizeof(thread_name), "main:%lu", pthread_self()); prctl(PR_SET_NAME, thread_name); // 加载配置 test_info_s test_info; if (test_load_config(config, ring_type, burst_cnt, &test_info.cfg) != 0) { - BBQ_ERR_LOG("load config error"); + TEST_ERR_LOG("load config error"); return -1; } @@ -125,14 +123,14 @@ int main(int argc, char *argv[]) { test_queue_s q; ret = bcm_queue_init(&test_info.cfg, &q); if (ret != 0) { - BBQ_ERR_LOG("init failed :%d", ret); + TEST_ERR_LOG("init failed :%d", ret); return ret; } // 创建线程 pthread_t *threads = test_threads_create(&test_info, &q); if (threads == NULL) { - BBQ_ERR_LOG("pthread_arr is NULL"); + TEST_ERR_LOG("pthread_arr is NULL"); return ret; } @@ -153,8 +151,8 @@ int main(int argc, char *argv[]) { test_free(TEST_MODULE_BCM, exit_data); test_threads_destory(&test_info, threads); test_queue_destory(&q); - bbq_memory_info(); - test_memory_info(); + bbq_memory_print(); + test_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 f285747..53dbc6a 100644 --- a/perf/benchmark/bcm_loadconfig.c +++ b/perf/benchmark/bcm_loadconfig.c @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-11 18:05:56 + * @LastEditTime: 2024-06-14 16:48:29 * @Email: [email protected] * @Describe: TODO */ @@ -11,7 +11,7 @@ int test_load_config(const char *config, const char *ring_type, uint32_t burst_cnt, test_cfg *cfg) { // 加载配置 - BBQ_INFO_LOG("load config:%s", config); + TEST_INFO_LOG("load config:%s", config); dictionary *ini = iniparser_load(config); if (ini == NULL) { return -1; @@ -37,7 +37,7 @@ int test_load_config(const char *config, const char *ring_type, uint32_t burst_c // 设置ring_type cfg->ring.ring_type = test_ring_type_str2enum(ring_type); if (cfg->ring.ring_type >= TEST_RING_TYPE_MAX) { - BBQ_ERR_LOG("unknown ring type:%d", cfg->ring.ring_type); + TEST_ERR_LOG("unknown ring type:%d", cfg->ring.ring_type); return -1; } cfg->ring.burst_cnt = burst_cnt; @@ -45,32 +45,32 @@ int test_load_config(const char *config, const char *ring_type, uint32_t burst_c if (cfg->ring.ring_type == TEST_RING_TYPE_RMIND) { // rmind仅支持1个消费者,仅支持burst方式 if (cfg->ring.consumer_cnt > 1) { - BBQ_ERR_LOG("ring type:%s only support single consumer", TEST_RING_TYPE_RMIND_STR); + TEST_ERR_LOG("ring type:%s only support single consumer", TEST_RING_TYPE_RMIND_STR); return -1; } if (cfg->ring.burst_cnt <= 1) { - BBQ_ERR_LOG("ring type:%s only support burst_cnt > 1 !", TEST_RING_TYPE_RMIND_STR); + TEST_ERR_LOG("ring type:%s only support burst_cnt > 1 !", TEST_RING_TYPE_RMIND_STR); return -1; } } if (cfg->run.run_time == 0 && cfg->run.run_ok_times == 0) { - BBQ_ERR_LOG("At least one of run_time or run_ok_times is not 0", TEST_RING_TYPE_RMIND_STR); + TEST_ERR_LOG("At least one of run_time or run_ok_times is not 0"); return -1; } - BBQ_INFO_LOG("introduce:%s", cfg->base.introduce); - BBQ_INFO_LOG("cores_cnt:%u", cfg->base.cores_cnt); - BBQ_INFO_LOG("workload:%s(%u)", workload, cfg->ring.workload); - BBQ_INFO_LOG("entries_cnt:%u", cfg->ring.entries_cnt); - BBQ_INFO_LOG("producer_cnt:%u", cfg->ring.producer_cnt); - BBQ_INFO_LOG("consumer_cnt:%u", cfg->ring.consumer_cnt); - BBQ_INFO_LOG("block_count:%u", cfg->ring.block_count); - BBQ_INFO_LOG("run_ok_times:%lu", cfg->run.run_ok_times); - BBQ_INFO_LOG("run_time:%lu", cfg->run.run_time); - BBQ_INFO_LOG("ring_type:%s(%u)", ring_type, cfg->ring.ring_type); - BBQ_INFO_LOG("burst_cnt:%u", burst_cnt); + 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); // 释放dictionary对象 iniparser_freedict(ini); diff --git a/perf/benchmark/bcm_queue.c b/perf/benchmark/bcm_queue.c index 9eec4f2..0cd09e8 100644 --- a/perf/benchmark/bcm_queue.c +++ b/perf/benchmark/bcm_queue.c @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-13 18:58:20 + * @LastEditTime: 2024-06-14 17:31:56 * @Email: [email protected] * @Describe: TODO */ @@ -8,7 +8,8 @@ #include "ringbuf.h" static __rte_always_inline unsigned int -bcm_dpdk_ring_enqueue_burst(struct rte_ring *r, void **obj_table, size_t n, uint16_t thread_idx) { +bcm_dpdk_ring_enqueue_burst(struct rte_ring *r, void **obj_table, uint32_t n, uint16_t thread_idx) { + TEST_AVOID_WARNING(thread_idx); return rte_ring_enqueue_burst(r, (void *const *)obj_table, n, NULL); } @@ -67,7 +68,7 @@ void test_queue_free_rmind(void *ring) { test_free(TEST_MODULE_RMIND, ring); } -uint32_t test_enqueue_burst_rmind(void *ring, void **obj_table, size_t n, unsigned int flags, uint16_t thread_idx) { +uint32_t test_enqueue_burst_rmind(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx) { uint32_t cnt = 0; int ret = 0; size_t off = 0; @@ -92,6 +93,7 @@ uint32_t test_enqueue_burst_rmind(void *ring, void **obj_table, size_t n, unsign } uint32_t test_dequeue_burst_rmind(void *ring, void *obj_table, uint32_t n) { + TEST_AVOID_WARNING(n); size_t len = 0; size_t off = 0; size_t per_size = sizeof(void *); diff --git a/perf/benchmark/benchmark.sh b/perf/benchmark/benchmark.sh index 272b6d6..6889de3 100755 --- a/perf/benchmark/benchmark.sh +++ b/perf/benchmark/benchmark.sh @@ -1,9 +1,9 @@ #!/bin/bash ### # @Author: liuyu -# @LastEditTime: 2024-06-14 10:19:30 +# @LastEditTime: 2024-06-14 14:37:48 # @Email: [email protected] -# @Describe: TODO +# @Describe: 运行性能测试的脚本 ### ring_type_arr=("bbq" "dpdk" "rmind") @@ -11,7 +11,7 @@ burst_arr=("32" "16" "8" "1") # 检查参数数量 if [ "$#" -ne 3 ]; then - echo "Usage: $0 <path_to_benchmark> <path_to_config_directory> <ring_type>" + echo "Usage: $0 <path to benchmark> <path to config file or directory> <ring type>" exit 1 fi @@ -24,6 +24,7 @@ function exec_benchmark_ring_type() { local ini="$1" local ring="$2" local log_file=$3 + local burst=$4 # 如果以perf开头的配置文件,还要执行perf统计 if [[ $(basename "$ini") == perf* ]]; then @@ -31,7 +32,7 @@ function exec_benchmark_ring_type() { # echo perf stat -a -e L1-dcache-loads,L1-dcache-load-misses,cache-references,cache-misses "$BENCHMARK_PATH" "$ini" "$ring" "$BURST_CNT" # perf stat -a -e L1-dcache-loads,L1-dcache-load-misses,cache-references,cache-misses "$BENCHMARK_PATH" "$ini" "$ring" "$BURST_CNT" else - "$BENCHMARK_PATH" "$ini" "$ring" "$BURST_CNT" 2>&1 | tee -a "$log_file" + "$BENCHMARK_PATH" "$ini" "$ring" "$burst" 2>&1 | tee -a "$log_file" fi } @@ -73,6 +74,9 @@ folder_path="/tmp/bbq/$timestamp" rm -rf "$folder_path" mkdir -p "$folder_path" +# 开始时间 +start_time=$(date +%s) + for burst in "${burst_arr[@]}"; do burst_dir="$folder_path"/burst_"$burst" mkdir -p "$burst_dir" @@ -94,4 +98,10 @@ for burst in "${burst_arr[@]}"; do sleep 1 done done -echo "done......." + +# 结束时间 +end_time=$(date +%s) +# 计算时间差(秒) +runtime=$((end_time - start_time)) +# 输出运行时间 +echo "done, use $runtime second" diff --git a/perf/benchmark/config/compare/general/case1_simple_spsc.ini b/perf/benchmark/config/compare/case1_simple_spsc.ini index de92814..de92814 100644 --- a/perf/benchmark/config/compare/general/case1_simple_spsc.ini +++ b/perf/benchmark/config/compare/case1_simple_spsc.ini diff --git a/perf/benchmark/config/compare/general/case2_simple_spmc.ini b/perf/benchmark/config/compare/case2_simple_spmc.ini index 4d1d06e..4d1d06e 100644 --- a/perf/benchmark/config/compare/general/case2_simple_spmc.ini +++ b/perf/benchmark/config/compare/case2_simple_spmc.ini diff --git a/perf/benchmark/config/compare/general/case3_simple_mpsc.ini b/perf/benchmark/config/compare/case3_simple_mpsc.ini index 89af5fc..89af5fc 100644 --- a/perf/benchmark/config/compare/general/case3_simple_mpsc.ini +++ b/perf/benchmark/config/compare/case3_simple_mpsc.ini diff --git a/perf/benchmark/config/compare/general/case4_complex_spmc.ini b/perf/benchmark/config/compare/case4_complex_spmc.ini index 6fcd711..6fcd711 100644 --- a/perf/benchmark/config/compare/general/case4_complex_spmc.ini +++ b/perf/benchmark/config/compare/case4_complex_spmc.ini diff --git a/perf/benchmark/config/compare/general/case5_complex_mpsc.ini b/perf/benchmark/config/compare/case5_complex_mpsc.ini index faeee45..faeee45 100644 --- a/perf/benchmark/config/compare/general/case5_complex_mpsc.ini +++ b/perf/benchmark/config/compare/case5_complex_mpsc.ini diff --git a/perf/benchmark/config/compare/general/case6_simple_mp0c.ini b/perf/benchmark/config/compare/case6_simple_mp0c.ini index f2d6952..f2d6952 100644 --- a/perf/benchmark/config/compare/general/case6_simple_mp0c.ini +++ b/perf/benchmark/config/compare/case6_simple_mp0c.ini diff --git a/perf/benchmark/config/compare/general/case7_simple_0pmc.ini b/perf/benchmark/config/compare/case7_simple_0pmc.ini index f4273ea..f4273ea 100644 --- a/perf/benchmark/config/compare/general/case7_simple_0pmc.ini +++ b/perf/benchmark/config/compare/case7_simple_0pmc.ini diff --git a/perf/benchmark/config/compare/general/case8_simple_mpmc.ini b/perf/benchmark/config/compare/case8_simple_mpmc.ini index 0ed2a25..0ed2a25 100644 --- a/perf/benchmark/config/compare/general/case8_simple_mpmc.ini +++ b/perf/benchmark/config/compare/case8_simple_mpmc.ini diff --git a/perf/benchmark/config/compare/general/case9_simple_mpmc_overcore.ini b/perf/benchmark/config/compare/case9_simple_mpmc_overcore.ini index bbbb46d..bbbb46d 100644 --- a/perf/benchmark/config/compare/general/case9_simple_mpmc_overcore.ini +++ b/perf/benchmark/config/compare/case9_simple_mpmc_overcore.ini diff --git a/perf/benchmark/config/compare/perf/perf_case1_simple_spsc.ini b/perf/benchmark/config/compare/perf/perf_case1_simple_spsc.ini deleted file mode 100644 index e45848a..0000000 --- a/perf/benchmark/config/compare/perf/perf_case1_simple_spsc.ini +++ /dev/null @@ -1,14 +0,0 @@ -[base] - introduce = "perf case1 简单负载下,单生产者、单消费者" ;测试配置说明 - cores_cnt = 8 ;测试用核心个数 - -[ring] - workload = "simple" ;负载模式 simple/complex - entries_cnt = 4096 ;ring初始化时分配entry的个数 - block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 - producer_cnt = 1 ;生产者个数 - consumer_cnt = 1 ;消费者个数 - -[run] - run_time = 10 ; 整体运行的秒数,大于0生效 - run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/perf/perf_case2_simple_mpmc.ini b/perf/benchmark/config/compare/perf/perf_case2_simple_mpmc.ini deleted file mode 100644 index eee9566..0000000 --- a/perf/benchmark/config/compare/perf/perf_case2_simple_mpmc.ini +++ /dev/null @@ -1,14 +0,0 @@ -[base] - introduce = "perf case2 简单负载下,多生产者、多消费者" ;测试配置说明 - cores_cnt = 8 ;测试用核心个数 - -[ring] - workload = "simple" ;负载模式 simple/complex - entries_cnt = 4096 ;ring初始化时分配entry的个数 - block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 - producer_cnt = 4 ;生产者个数 - consumer_cnt = 4 ;消费者个数 - -[run] - run_time = 10 ; 整体运行的秒数,大于0生效 - run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/perf/perf_case3_simple_spmp.ini b/perf/benchmark/config/compare/perf/perf_case3_simple_spmp.ini deleted file mode 100644 index 8356282..0000000 --- a/perf/benchmark/config/compare/perf/perf_case3_simple_spmp.ini +++ /dev/null @@ -1,14 +0,0 @@ -[base] - introduce = "perf case3 简单负载下,单生产者、多消费者" ;测试配置说明 - cores_cnt = 8 ;测试用核心个数 - -[ring] - workload = "simple" ;负载模式 simple/complex - entries_cnt = 4096 ;ring初始化时分配entry的个数 - block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 - producer_cnt = 1 ;生产者个数 - consumer_cnt = 4 ;消费者个数 - -[run] - run_time = 10 ; 整体运行的秒数,大于0生效 - run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/perf/perf_case4_simple_mpsc.ini b/perf/benchmark/config/compare/perf/perf_case4_simple_mpsc.ini deleted file mode 100644 index edc0001..0000000 --- a/perf/benchmark/config/compare/perf/perf_case4_simple_mpsc.ini +++ /dev/null @@ -1,14 +0,0 @@ -[base] - introduce = "perf case4 简单负载下,多生产者、单消费者" ;测试配置说明 - cores_cnt = 8 ;测试用核心个数 - -[ring] - workload = "simple" ;负载模式 simple/complex - entries_cnt = 4096 ;ring初始化时分配entry的个数 - block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 - producer_cnt = 4 ;生产者个数 - consumer_cnt = 1 ;消费者个数 - -[run] - run_time = 10 ; 整体运行的秒数,大于0生效 - run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file |
