From 8c5d72375a2a0ea590832aeeb3303e6bc7f6ae01 Mon Sep 17 00:00:00 2001 From: 刘煜 Date: Tue, 11 Jun 2024 10:14:19 +0000 Subject: benchmark绑定核心、rocky linux编译失败问题 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bbq/include/bbq.h | 4 +- bbq/tests/common/test_mix.c | 19 ++- bbq/tests/common/test_mix.h | 100 +++++++------ bbq/tests/common/test_queue.c | 163 +++++++++++---------- bbq/tests/common/test_queue.h | 15 +- bbq/tests/unittest/ut_data.cc | 56 ++++--- bbq/tests/unittest/ut_head_cursor.cc | 86 ++++++----- bbq/tests/unittest/ut_mix.cc | 1 - perf/CMakeLists.txt | 2 + perf/benchmark/CMakeLists.txt | 2 +- perf/benchmark/bcm_benchmark.c | 45 +++--- perf/benchmark/bcm_loadconfig.c | 23 +-- .../config/compare/general/case1_simple_spsc.ini | 2 +- .../config/compare/general/case2_simple_spmc.ini | 2 +- .../config/compare/general/case3_simple_mpsc.ini | 2 +- .../config/compare/general/case4_complex_spmc.ini | 2 +- .../config/compare/general/case5_complex_mpsc.ini | 2 +- .../config/compare/general/case6_simple_mp0c.ini | 2 +- .../config/compare/general/case7_simple_0pmc.ini | 2 +- .../config/compare/general/case8_simple_mpmc.ini | 2 +- .../compare/general/case9_simple_mpmc_overcore.ini | 2 +- .../config/compare/perf/perf_case1_simple_spsc.ini | 2 +- .../config/compare/perf/perf_case2_simple_mpmc.ini | 2 +- .../config/compare/perf/perf_case3_simple_spmp.ini | 2 +- .../config/compare/perf/perf_case4_simple_mpsc.ini | 2 +- 25 files changed, 279 insertions(+), 263 deletions(-) diff --git a/bbq/include/bbq.h b/bbq/include/bbq.h index 61d4f66..d08b316 100644 --- a/bbq/include/bbq.h +++ b/bbq/include/bbq.h @@ -1,6 +1,6 @@ /* * @Author: liuyu@geedgenetworks.com - * @LastEditTime: 2024-06-06 10:07:17 + * @LastEditTime: 2024-06-07 16:30:54 * @Describe: bbq(Block-based Bounded Queue)头文件 * 参考:https://www.usenix.org/system/files/atc22-wang-jiawei.pdf */ @@ -8,7 +8,6 @@ #ifndef _BBQ_H_ #define _BBQ_H_ -#include #include #include #include @@ -18,6 +17,7 @@ #ifndef __cplusplus // C +#include typedef atomic_uint_fast64_t aotmic_uint64; typedef aotmic_uint64 bbq_cursor; typedef aotmic_uint64 bbq_head; diff --git a/bbq/tests/common/test_mix.c b/bbq/tests/common/test_mix.c index 1a3869e..1009c81 100644 --- a/bbq/tests/common/test_mix.c +++ b/bbq/tests/common/test_mix.c @@ -1,11 +1,12 @@ /* * @Description: 描述信息 * @Date: 2024-05-25 10:55:48 - * @LastEditTime: 2024-06-06 18:55:12 + * @LastEditTime: 2024-06-07 16:54:45 */ - +#define _GNU_SOURCE #include "test_mix.h" #include "bbq.h" +#include #include #include @@ -204,3 +205,17 @@ void test_enqueue_table_destory(uint16_t **table, uint32_t count) { } test_free(TEST_MODULE_TABLE, table); } + +int test_setaffinity(int core_id) { + cpu_set_t mask; + CPU_ZERO(&mask); + + CPU_SET(core_id, &mask); + + if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == -1) { + fprintf(stderr, "pthread_setaffinity_np erro\n"); + return BBQ_ERROR; + } + + return BBQ_OK; +} \ No newline at end of file diff --git a/bbq/tests/common/test_mix.h b/bbq/tests/common/test_mix.h index 511378f..82b3d7f 100644 --- a/bbq/tests/common/test_mix.h +++ b/bbq/tests/common/test_mix.h @@ -1,18 +1,23 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-07 00:43:49 + * @LastEditTime: 2024-06-11 11:48:13 * @Email: liuyu@geedgenetworks.com * @Describe: TODO */ #ifndef _TEST_MIX_H_ #define _TEST_MIX_H_ -#include +#include #include #include #include #include +#ifndef __cplusplus +// C +#include +#endif + #define TEST_TABLE_DATA_MAGIC 12345 typedef enum { @@ -22,22 +27,22 @@ typedef enum { } test_thread_type_e; typedef struct { - struct timespec timestamp; // 系统时间戳 + struct timespec timestamp; // 系统时间戳 // uint64_t cycles; // cpu运行的cycle } test_time_metric; typedef struct { - uint64_t throughput; // 吞吐量:每秒消耗的条目总数。 - double data_latency; // 数据延迟:每个数据在队列中停留的平均时间。 - double op_latency; // 操作延迟:每个入队或出队操作的平均延迟。 - double* fairness; // 公平性:每个生产者/消费者的吞吐量(占总吞吐的百分比) - double full_empty; // 队列满时入队的延迟/队列空时出队的延迟(仅用于简单工作负载)。 - uint64_t oversubscription; // 比核心/超线程更多的生产者和消费者的吞吐量 + uint64_t throughput; // 吞吐量:每秒消耗的条目总数。 + double data_latency; // 数据延迟:每个数据在队列中停留的平均时间。 + double op_latency; // 操作延迟:每个入队或出队操作的平均延迟。 + double *fairness; // 公平性:每个生产者/消费者的吞吐量(占总吞吐的百分比) + double full_empty; // 队列满时入队的延迟/队列空时出队的延迟(仅用于简单工作负载)。 + uint64_t oversubscription; // 比核心/超线程更多的生产者和消费者的吞吐量 } test_report; typedef enum { - TEST_WORKLOAD_SIMPLE, // 简单负载,每个生产者或消费者都有自己的线程,它们在循环中不断执行入队或出队操作。每次出队后都会验证数据。 - TEST_WORKLOAD_COMPLEX, // 复杂负载,基于简单工作负载。生产者和消费者为数据分配空间,执行入队和出队,然后手动释放 + TEST_WORKLOAD_SIMPLE, // 简单负载,每个生产者或消费者都有自己的线程,它们在循环中不断执行入队或出队操作。每次出队后都会验证数据。 + TEST_WORKLOAD_COMPLEX, // 复杂负载,基于简单工作负载。生产者和消费者为数据分配空间,执行入队和出队,然后手动释放 TEST_WORKLOAD_MAX, } test_workload_e; @@ -52,42 +57,48 @@ typedef enum { } test_ring_type; typedef struct { - char name[128]; // 配置文件名 - char introduce[128]; // 测试配置说明 - uint16_t cores_cnt; // 测试用核心个数 + char name[128]; // 配置文件名 + char introduce[128]; // 测试配置说明 + uint16_t cores_cnt; // 测试用核心个数 } test_cfg_base; typedef struct { - test_ring_type ring_type; // ring buffer类型 - uint32_t producer_cnt; // 生产者个数 - uint32_t consumer_cnt; // 消费者个数 - test_workload_e workload; // 负载模式 - uint64_t entries_cnt; // ring初始化时分配entry的个数 - uint32_t block_count; // bbq block个数,为0时表示根据entries_cnt自动计算 - uint32_t burst_cnt; // 批量出入队个数 + test_ring_type ring_type; // ring buffer类型 + uint32_t producer_cnt; // 生产者个数 + uint32_t consumer_cnt; // 消费者个数 + test_workload_e workload; // 负载模式 + uint64_t entries_cnt; // ring初始化时分配entry的个数 + uint32_t block_count; // bbq block个数,为0时表示根据entries_cnt自动计算 + uint32_t burst_cnt; // 批量出入队个数 } test_cfg_ring; typedef struct { - uint64_t run_ok_times; // 成功入队/入队次数 - uint64_t run_time; // 整体运行时间,单位秒 - volatile bool running; // 默认为true,当设置为false,即所有生产者消费者即将退出 + uint64_t run_ok_times; // 成功入队/入队次数 + uint64_t run_time; // 整体运行时间,单位秒 +} test_cfg_run; + +typedef struct { + test_cfg_base base; + test_cfg_ring ring; + test_cfg_run run; +} test_cfg; +typedef struct { + volatile bool running; // 默认为true,当设置为false,即所有生产者消费者即将退出 + pthread_barrier_t all_threads_start; #ifndef __cplusplus // C - atomic_uint thread_start; atomic_uint producer_exit; #else // C++ 为了兼容gtest测试 - std::atomic thread_start; std::atomic producer_exit; #endif -} test_cfg_run; +} test_ctl; typedef struct { - test_cfg_base base; - test_cfg_ring ring; - test_cfg_run run; -} test_cfg; + test_cfg cfg; + test_ctl ctl; +} test_info_s; typedef enum { TEST_MODULE_UTEST, @@ -101,20 +112,21 @@ typedef enum { extern test_time_metric test_clock_time_get(); extern test_time_metric test_clock_time_sub(test_time_metric now, test_time_metric last); -extern int test_load_config(const char* config, const char* ring_type, uint32_t burst_cnt, test_cfg* cfg); -extern test_workload_e test_workload_str2enum(const char* workload); -extern test_ring_type test_ring_type_str2enum(const char* ring_type); -extern bool test_clock_time_is_zero(test_time_metric* metric); -extern bool test_timespec_is_after(const struct timespec* a, const struct timespec* b); -extern char* test_ring_type_enum2str(test_ring_type ring_type); -extern uint64_t test_clock_time_to_ns(test_time_metric* metric); -extern double test_clock_time_to_double(test_time_metric* metric); -extern void* test_malloc(test_module_e module, size_t size); -extern void* test_calloc(test_module_e module, size_t size); -extern void test_free(test_module_e module, void* ptr); +extern int test_load_config(const char *config, const char *ring_type, uint32_t burst_cnt, test_cfg *cfg); +extern test_workload_e test_workload_str2enum(const char *workload); +extern test_ring_type test_ring_type_str2enum(const char *ring_type); +extern bool test_clock_time_is_zero(test_time_metric *metric); +extern bool test_timespec_is_after(const struct timespec *a, const struct timespec *b); +extern char *test_ring_type_enum2str(test_ring_type ring_type); +extern uint64_t test_clock_time_to_ns(test_time_metric *metric); +extern double test_clock_time_to_double(test_time_metric *metric); +extern void *test_malloc(test_module_e module, size_t size); +extern void *test_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_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 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); #endif \ No newline at end of file diff --git a/bbq/tests/common/test_queue.c b/bbq/tests/common/test_queue.c index 56ab253..d8787e5 100644 --- a/bbq/tests/common/test_queue.c +++ b/bbq/tests/common/test_queue.c @@ -1,25 +1,18 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-07 00:38:03 + * @LastEditTime: 2024-06-11 11:46:12 * @Email: liuyu@geedgenetworks.com * @Describe: TODO */ #include "test_queue.h" -#include -#include #include "bbq.h" #include "test_mix.h" +#include +#include -void test_busy_loop(uint32_t busy_loop) { - uint32_t loop = 0; - while (loop <= busy_loop) { - loop++; - }; -} - -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) { + bbq_queue_s *ring; size_t obj_size = sizeof(test_data); if (cfg->ring.block_count == 0) { @@ -36,7 +29,7 @@ int test_queue_init_bbq(test_cfg* cfg, test_queue_s* q) { return BBQ_NULL_PTR; } - bbq_queue_s* bbq_ring = (bbq_queue_s*)q->ring; + 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; @@ -48,36 +41,29 @@ int test_queue_init_bbq(test_cfg* cfg, test_queue_s* q) { 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_cfg* cfg) { - return atomic_load(&cfg->run.producer_exit) == cfg->ring.producer_cnt; +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_cfg* cfg) { - uint32_t thread_cnt_max = cfg->ring.consumer_cnt + - cfg->ring.producer_cnt; - - while (atomic_load(&cfg->run.thread_start) != thread_cnt_max) { - // 忙等待其他线程准备好 - // BBQ_DBG_LOG("wait all thread init done!"); - // sleep(1); - } +void test_wait_all_threads_ready(test_ctl *ctl) { + pthread_barrier_wait(&ctl->all_threads_start); BBQ_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"); exit(-1); } - size_t size = t_arg->cfg->ring.entries_cnt; + size_t size = t_arg->test_info->cfg.ring.entries_cnt; exit_data->simple_data_cnt = size; exit_data->simple_data = test_data_create(size); @@ -93,14 +79,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) { +test_exit_data *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])); @@ -111,14 +97,14 @@ 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(); if (burst_cnt == 1) { @@ -135,7 +121,7 @@ uint32_t test_exec_enqueue(test_queue_s* q, test_data** data, size_t burst_cnt, 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(); @@ -153,15 +139,16 @@ uint32_t test_exec_dequeue(test_queue_s* q, test_data** data, size_t burst_cnt, return dequeue_cnt; } -void* test_thread_producer_start(void* arg) { +void *test_thread_producer_start(void *arg) { int ret = 0; 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_cfg* cfg = t_arg->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; @@ -171,13 +158,16 @@ void* test_thread_producer_start(void* arg) { snprintf(thread_name, sizeof(thread_name), "producer:%x", exit_data->thread_id); prctl(PR_SET_NAME, thread_name); + if (test_setaffinity(t_arg->core) != BBQ_OK) { + BBQ_ERR_LOG("test_setaffinity error"); + exit(-1); + } - atomic_fetch_add(&cfg->run.thread_start, 1); - test_wait_all_threads_ready(cfg); + test_wait_all_threads_ready(&test_info->ctl); exit_data->metric_start = test_clock_time_get(); while (true) { - if ((run_ok_times > 0 && ok_cnt >= run_ok_times) || (!cfg->run.running)) { + if ((run_ok_times > 0 && ok_cnt >= run_ok_times) || (!test_info->ctl.running)) { // 控制次数的循环或运行时间到了 break; } @@ -186,7 +176,7 @@ 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"); exit(-1); @@ -197,7 +187,6 @@ void* test_thread_producer_start(void* arg) { } test_free(TEST_MODULE_DATA, data); - test_busy_loop(t_arg->busy_loop); } if (enqueue_cnt > 0) { @@ -216,39 +205,43 @@ void* test_thread_producer_start(void* arg) { exit_data->op_ok_latency_ns = op_ok_latency_ns; exit_data->op_err_latency_ns = op_err_latency_ns; - atomic_fetch_add(&cfg->run.producer_exit, 1); + atomic_fetch_add(&test_info->ctl.producer_exit, 1); BBQ_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_cfg* cfg = t_arg->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_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); prctl(PR_SET_NAME, thread_name); + if (test_setaffinity(t_arg->core) != BBQ_OK) { + BBQ_ERR_LOG("test_setaffinity error"); + exit(-1); + } - atomic_fetch_add(&cfg->run.thread_start, 1); - test_wait_all_threads_ready(cfg); + test_wait_all_threads_ready(&test_info->ctl); exit_data->metric_start = test_clock_time_get(); uint32_t last_times = cfg->ring.entries_cnt; while (true) { - if (!cfg->run.running || test_all_producer_exit(cfg)) { + if (!test_info->ctl.running || test_all_producer_exit(test_info)) { // 运行时间到了或是所有生产者退出了,检查生产者是否全部退出,且队列被消费完了 if (deq_cnt == 0 && (last_times-- <= 0)) { break; @@ -258,8 +251,8 @@ 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]; - if (t_arg->cfg->ring.workload == TEST_WORKLOAD_SIMPLE) { + 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); exit_data->data_error_cnt += 1; @@ -278,7 +271,6 @@ void* test_thread_consumer_start(void* arg) { latency_ns += test_clock_time_to_ns(&latency); test_free(TEST_MODULE_DATA, data); - test_busy_loop(t_arg->busy_loop); } } ok_cnt += deq_cnt; @@ -303,23 +295,26 @@ void* test_thread_consumer_start(void* arg) { pthread_exit(exit_data); } -void test_check_run_time(test_cfg* cfg) { - if (cfg->run.run_time > 0) { +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...", cfg->run.run_time); - sleep(cfg->run.run_time); - cfg->run.running = false; + 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_t* -test_one_thread_create(test_cfg* cfg, test_queue_s* q, test_thread_type_e ttype, int core, uint16_t thread_id, pthread_t* thread) { +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 - arg->cfg = cfg; + 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; arg->core = core; - arg->busy_loop = (core + 1) * 7 % 100; arg->thread_idx = thread_id; if (ttype == TEST_THREAD_PRODUCER) { @@ -334,47 +329,52 @@ test_one_thread_create(test_cfg* cfg, test_queue_s* q, test_thread_type_e ttype, core_id = (core_id + 1) < max_id ? (core_id + 1) : core_id; \ } while (0) -pthread_t* test_threads_create(test_cfg* cfg, 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; 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; + test_info->ctl.producer_exit = ATOMIC_VAR_INIT(0); // MPSC 或 SPMC 场景在第一个核心/超线程上分配单个生产者或消费者,然后将其他线程按顺序分配给核心/超线程。 // MPMC,我们将生产者和消费者一一交错分配 // 如果数量不同,则在最后分配剩余部分。 if (cfg->ring.producer_cnt == 1 && cfg->ring.consumer_cnt >= 1) { // SPMC,第一个核心给生产者,其他分配给消费者 - test_one_thread_create(cfg, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); + 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++) { CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); - test_one_thread_create(cfg, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); + test_one_thread_create(test_info, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); thread_id++; } } else if (cfg->ring.consumer_cnt == 1 && cfg->ring.producer_cnt >= 1) { // MPSC,第一个核心给消费者,其他分配给生产者 - test_one_thread_create(cfg, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); + 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++) { CORE_ID_CHK_SET(core_id, cfg->base.cores_cnt); - test_one_thread_create(cfg, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); + 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) { // 偶数 - test_one_thread_create(cfg, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); + test_one_thread_create(test_info, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); thread_id++; pcnt--; } else { - test_one_thread_create(cfg, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); + test_one_thread_create(test_info, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); thread_id++; ccnt--; } @@ -382,13 +382,13 @@ pthread_t* test_threads_create(test_cfg* cfg, test_queue_s* q) { } for (int i = 0; i < pcnt; i++) { - test_one_thread_create(cfg, q, TEST_THREAD_PRODUCER, core_id, thread_id, &(threads[thread_id])); + 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++) { - test_one_thread_create(cfg, q, TEST_THREAD_CONSUMER, core_id, thread_id, &(threads[thread_id])); + 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); } @@ -397,11 +397,12 @@ pthread_t* test_threads_create(test_cfg* cfg, test_queue_s* q) { return threads; } -void test_threads_destory(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; @@ -410,7 +411,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 0d6454f..ed2800a 100644 --- a/bbq/tests/common/test_queue.h +++ b/bbq/tests/common/test_queue.h @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-06 16:39:11 + * @LastEditTime: 2024-06-11 11:31:10 * @Email: liuyu@geedgenetworks.com * @Describe: TODO */ @@ -32,9 +32,8 @@ typedef struct { typedef struct { int core; uint16_t thread_idx; // 线程索引,不是pthread_id - uint32_t busy_loop; // 忙循环次数 test_thread_type_e ttype; - test_cfg *cfg; + test_info_s *test_info; test_queue_s *q; } test_thread_arg_s; @@ -78,17 +77,17 @@ typedef struct { test_merge_data consumer; } test_merge_s; -extern void test_threads_destory(pthread_t *threads); -extern pthread_t *test_threads_create(test_cfg *cfg, test_queue_s *q); -extern pthread_t *test_one_thread_create(test_cfg *cfg, test_queue_s *q, test_thread_type_e ttype, int core, uint16_t thread_id, pthread_t *thread); -extern void test_check_run_time(test_cfg *cfg); +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_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 test_exit_data *test_exit_data_create(test_thread_arg_s *t_arg); -extern void test_wait_all_threads_ready(test_cfg *cfg); +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); diff --git a/bbq/tests/unittest/ut_data.cc b/bbq/tests/unittest/ut_data.cc index 493c003..81a17da 100644 --- a/bbq/tests/unittest/ut_data.cc +++ b/bbq/tests/unittest/ut_data.cc @@ -1,6 +1,6 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-07 00:51:44 + * @LastEditTime: 2024-06-11 11:31:52 * @Email: liuyu@geedgenetworks.com * @Describe: TODO */ @@ -18,45 +18,41 @@ extern void bbq_memory_info(); TEST(data, correct) { test_memory_counter_clear(); - test_cfg cfg = { - .base = { - .name = "data correct", - .introduce = "data correct", - .cores_cnt = 4, - }, - .ring = { - .ring_type = TEST_RING_TYPE_BBQ, - .producer_cnt = 5, - .consumer_cnt = 5, - .workload = TEST_WORKLOAD_SIMPLE, - .entries_cnt = 4096, - .block_count = 0, - .burst_cnt = 1, - }, - .run = { - .run_ok_times = 50000, - .running = true, + test_info_s test_info{ + .cfg = { + .base = { + .cores_cnt = 4, + }, + .ring = { + .ring_type = TEST_RING_TYPE_BBQ, + .producer_cnt = 5, + .consumer_cnt = 5, + .workload = TEST_WORKLOAD_SIMPLE, + .entries_cnt = 4096, + .block_count = 0, + .burst_cnt = 1, + }, + .run = { + .run_ok_times = 50000, + }, }, + .ctl = {.running = true}, }; // 队列初始化 int ret = -1; test_queue_s q; - ret = test_queue_init_bbq(&cfg, &q); + ret = test_queue_init_bbq(&test_info.cfg, &q); ASSERT_TRUE(ret == 0); // 创建线程 - pthread_t* threads = test_threads_create(&cfg, &q); + pthread_t *threads = test_threads_create(&test_info, &q); ASSERT_TRUE(threads); // 等待所有线程完成,回收数据 - uint32_t thread_cnt = cfg.ring.producer_cnt + cfg.ring.consumer_cnt; - test_exit_data** exit_data = (test_exit_data**)test_malloc(TEST_MODULE_UTEST, sizeof(test_exit_data**) * (thread_cnt)); - uint32_t i = 0; - - for (i = 0; i < thread_cnt; i++) { - pthread_join(threads[i], (void**)(&exit_data[i])); // 等待每个线程结束 - } + uint32_t thread_cnt = test_info.cfg.ring.producer_cnt + test_info.cfg.ring.consumer_cnt; + test_exit_data **exit_data = (test_exit_data **)test_malloc(TEST_MODULE_UTEST, sizeof(test_exit_data **) * (thread_cnt)); + test_wait_all_threads_exit(&test_info, thread_cnt, threads, exit_data); // 比较数据 test_merge_s merge = {0}; @@ -65,11 +61,11 @@ TEST(data, correct) { EXPECT_EQ(merge.consumer.ok_cnt, merge.producer.ok_cnt); // 释放数据 - for (i = 0; i < thread_cnt; i++) { + for (uint32_t i = 0; i < thread_cnt; i++) { test_exit_data_destory(exit_data[i]); } test_free(TEST_MODULE_UTEST, exit_data); - test_threads_destory(threads); + test_threads_destory(&test_info, threads); test_queue_destory(&q); EXPECT_TRUE(bbq_malloc_free_equal()); EXPECT_TRUE(test_malloc_free_equal()); diff --git a/bbq/tests/unittest/ut_head_cursor.cc b/bbq/tests/unittest/ut_head_cursor.cc index be65906..8fe5dae 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-07 01:13:55 + * @LastEditTime: 2024-06-11 11:32:48 * @Email: liuyu@geedgenetworks.com * @Describe: TODO */ @@ -12,32 +12,32 @@ extern bool bbq_malloc_free_equal(); extern void bbq_memory_info(); } -void expect_phead(bbq_queue_s* q, uint64_t idx, uint64_t vsn, int line) { +void expect_phead(bbq_queue_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(bbq_queue_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(bbq_queue_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(bbq_queue_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(bbq_queue_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(bbq_queue_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; } @@ -47,7 +47,7 @@ TEST(head_cursor, init) { test_memory_counter_clear(); int ret = 0; - bbq_queue_s* q; + bbq_queue_s *q; uint32_t bn = 2; uint32_t bs = 4; int enqueue_data = TEST_DATA_MAGIC; @@ -77,7 +77,7 @@ TEST(head_cursor, init) { void ut_produce_something(uint32_t produce_cnt) { int ret = 0; - bbq_queue_s* q; + bbq_queue_s *q; uint32_t bn = 8; uint32_t bs = 4096; int enqueue_data = TEST_DATA_MAGIC; @@ -139,7 +139,7 @@ TEST(head_cursor, produce_something) { void ut_produce_next_block(uint32_t over) { int ret = 0; - bbq_queue_s* q; + bbq_queue_s *q; uint32_t bn = 8; uint32_t bs = 4096; uint32_t produce_cnt = bs + over; @@ -206,7 +206,7 @@ TEST(head_cursor, produce_next_block) { void ut_produce_all_loop(uint32_t loop) { int ret = 0; - bbq_queue_s* q; + bbq_queue_s *q; uint32_t bn = 8; uint32_t bs = 4096; uint32_t produce_cnt = bn * bs; @@ -264,9 +264,9 @@ TEST(boundary, retry_new_full_empty) { int ret = 0; uint32_t entries_cnt = 4096; uint32_t loop = 1000; - bbq_queue_s* q; + bbq_queue_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); @@ -328,47 +328,43 @@ TEST(boundary, retry_new_full_empty) { TEST(boundary, mpsc_faa) { test_memory_counter_clear(); - test_cfg cfg = { - .base = { - .name = "mpsc_faa", - .introduce = "mpsc_faa", - .cores_cnt = 4, - }, - .ring = { - .ring_type = TEST_RING_TYPE_BBQ, - .producer_cnt = 10, - .consumer_cnt = 1, - .workload = TEST_WORKLOAD_SIMPLE, - .entries_cnt = 1, - .block_count = 1, - .burst_cnt = 1, - }, - .run = { - .run_time = 5, - .running = true, + test_info_s test_info = { + .cfg = { + .base = { + .cores_cnt = 4, + }, + .ring = { + .ring_type = TEST_RING_TYPE_BBQ, + .producer_cnt = 10, + .consumer_cnt = 1, + .workload = TEST_WORKLOAD_SIMPLE, + .entries_cnt = 1, + .block_count = 1, + .burst_cnt = 1, + }, + .run = { + .run_time = 5, + }, }, + .ctl = {.running = true}, }; // 队列初始化 int ret = -1; test_queue_s q; - ret = test_queue_init_bbq(&cfg, &q); + ret = test_queue_init_bbq(&test_info.cfg, &q); ASSERT_TRUE(ret == 0); // 创建线程 - pthread_t* threads = test_threads_create(&cfg, &q); + pthread_t *threads = test_threads_create(&test_info, &q); ASSERT_TRUE(threads); // 等待所有线程完成,回收数据 - uint32_t thread_cnt = cfg.ring.producer_cnt + cfg.ring.consumer_cnt; - test_exit_data** exit_data = (test_exit_data**)test_malloc(TEST_MODULE_UTEST, sizeof(test_exit_data**) * (thread_cnt)); + uint32_t thread_cnt = test_info.cfg.ring.producer_cnt + test_info.cfg.ring.consumer_cnt; + test_exit_data **exit_data = (test_exit_data **)test_malloc(TEST_MODULE_UTEST, sizeof(test_exit_data **) * (thread_cnt)); uint32_t i = 0; - test_check_run_time(&cfg); - - for (i = 0; i < thread_cnt; i++) { - pthread_join(threads[i], (void**)(&exit_data[i])); // 等待每个线程结束 - } + test_wait_all_threads_exit(&test_info, thread_cnt, threads, exit_data); // 比较数据 test_merge_s merge = {0}; @@ -381,18 +377,18 @@ TEST(boundary, mpsc_faa) { test_exit_data_destory(exit_data[i]); } test_free(TEST_MODULE_UTEST, exit_data); - test_threads_destory(threads); + test_threads_destory(&test_info, threads); test_queue_destory(&q); EXPECT_TRUE(bbq_malloc_free_equal()); EXPECT_TRUE(test_malloc_free_equal()); } -void debug_head_print(bbq_queue_s* q) { +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) { +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())); @@ -408,7 +404,7 @@ TEST(boundary, drop_old_full_empty1) { uint32_t bs = 4; uint32_t over_cnt = 3; uint32_t loop = 1000; - bbq_queue_s* q; + bbq_queue_s *q; int tmp_data = 0; q = bbq_ring_create_bnbs(bn, bs, sizeof(int), BBQ_F_COPY_VALUE | BBQ_F_POLICY_DROP_OLD); @@ -457,7 +453,7 @@ TEST(boundary, drop_old_full_empty2) { uint32_t bs = 4; uint32_t loop = 1000; uint32_t over_cnt = bs + 2; - bbq_queue_s* q; + bbq_queue_s *q; EXPECT_EQ(over_cnt / bs, 1); diff --git a/bbq/tests/unittest/ut_mix.cc b/bbq/tests/unittest/ut_mix.cc index 4b33524..e2b53e8 100644 --- a/bbq/tests/unittest/ut_mix.cc +++ b/bbq/tests/unittest/ut_mix.cc @@ -7,7 +7,6 @@ #include "gtest/gtest.h" extern "C" { #include -#include "bbq.h" #include "test_mix.h" #include "ut.h" extern bool bbq_check_power_of_two(int n); diff --git a/perf/CMakeLists.txt b/perf/CMakeLists.txt index b72c737..a361c80 100644 --- a/perf/CMakeLists.txt +++ b/perf/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../bbq/tests/common ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/iniparser ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/rmind_ringbuf + /home/admin/test/dpdk-23.07/build/install/include ) @@ -23,6 +24,7 @@ set(EXEC_PATH ${OUTPUT_DIR}/bin) # 指定库路径 link_directories(${LIB_PATH}) link_directories(../bbq/build/output/lib/) +link_directories(/home/admin/test/dpdk-23.07/build/install/lib64) # 可执行程序的名字 set(BENCHMARK_NAME benchmark) diff --git a/perf/benchmark/CMakeLists.txt b/perf/benchmark/CMakeLists.txt index 39bada7..0c3848d 100644 --- a/perf/benchmark/CMakeLists.txt +++ b/perf/benchmark/CMakeLists.txt @@ -10,4 +10,4 @@ list(APPEND SRC_LIST ${SRC_COMMON_LIST}) set(EXECUTABLE_OUTPUT_PATH ${EXEC_PATH}) add_executable(benchmark ${SRC_LIST}) # 添加可执行程序 -target_link_libraries(benchmark iniparser pthread rte_ring rte_eal rte_kvargs rte_telemetry rmind_ringbuf bbq m) # 链接库 \ No newline at end of file +target_link_libraries(benchmark dl iniparser pthread rte_ring rte_eal rte_kvargs rte_telemetry rmind_ringbuf bbq m) # 链接库 \ No newline at end of file diff --git a/perf/benchmark/bcm_benchmark.c b/perf/benchmark/bcm_benchmark.c index d66819c..7298bb7 100644 --- a/perf/benchmark/bcm_benchmark.c +++ b/perf/benchmark/bcm_benchmark.c @@ -1,25 +1,25 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-07 00:33:43 + * @LastEditTime: 2024-06-11 11:32:43 * @Email: liuyu@geedgenetworks.com * @Describe: TODO */ +#include "bbq.h" +#include "bcm_queue.h" +#include "iniparser.h" +#include "test_mix.h" +#include "test_queue.h" #include #include #include #include #include #include -#include "bbq.h" -#include "bcm_queue.h" -#include "iniparser.h" -#include "test_mix.h" -#include "test_queue.h" extern void bbq_memory_info(); 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) { +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) { char name[10] = {0}; double latency_ns = 0; double throughput = 0; @@ -66,7 +66,7 @@ void bcm_report_printf(test_cfg* cfg, test_merge_data* data, test_exit_data** ra } } -void bcm_report_generate(test_cfg* cfg, test_exit_data** exit_data, uint32_t thread_cnt) { +void bcm_report_generate(test_cfg *cfg, test_exit_data **exit_data, uint32_t thread_cnt) { // test_report report; test_merge_s merge = {0}; @@ -88,9 +88,9 @@ void bcm_report_generate(test_cfg* cfg, test_exit_data** exit_data, uint32_t thr } } -int main(int argc, char* argv[]) { - char* config; - char* ring_type; +int main(int argc, char *argv[]) { + char *config; + char *ring_type; uint32_t burst_cnt = 0; if (argc == 4) { @@ -114,8 +114,8 @@ int main(int argc, char* argv[]) { prctl(PR_SET_NAME, thread_name); // 加载配置 - test_cfg cfg; - if (test_load_config(config, ring_type, burst_cnt, &cfg) != 0) { + test_info_s test_info; + if (test_load_config(config, ring_type, burst_cnt, &test_info.cfg) != 0) { BBQ_ERR_LOG("load config error"); return -1; } @@ -123,40 +123,35 @@ int main(int argc, char* argv[]) { // 队列初始化 int ret = -1; test_queue_s q; - ret = bcm_queue_init(&cfg, &q); + ret = bcm_queue_init(&test_info.cfg, &q); if (ret != 0) { BBQ_ERR_LOG("init failed :%d", ret); return ret; } // 创建线程 - pthread_t* threads = test_threads_create(&cfg, &q); + pthread_t *threads = test_threads_create(&test_info, &q); if (threads == NULL) { BBQ_ERR_LOG("pthread_arr is NULL"); return ret; } - test_check_run_time(&cfg); - pthread_t thread_run_time; - // 等待所有线程完成,回收数据 - uint32_t thread_cnt = cfg.ring.producer_cnt + cfg.ring.consumer_cnt; - test_exit_data** exit_data = (test_exit_data**)test_malloc(TEST_MODULE_BCM, sizeof(test_exit_data**) * (thread_cnt)); + uint32_t thread_cnt = test_info.cfg.ring.producer_cnt + test_info.cfg.ring.consumer_cnt; + test_exit_data **exit_data = (test_exit_data **)test_malloc(TEST_MODULE_BCM, sizeof(test_exit_data **) * (thread_cnt)); uint32_t i = 0; - for (i = 0; i < thread_cnt; i++) { - pthread_join(threads[i], (void**)(&exit_data[i])); // 等待每个线程结束 - } + test_wait_all_threads_exit(&test_info, thread_cnt, threads, exit_data); // 生成benchmark报告 - bcm_report_generate(&cfg, exit_data, thread_cnt); + bcm_report_generate(&test_info.cfg, exit_data, thread_cnt); // 回收、释放数据 for (i = 0; i < thread_cnt; i++) { test_exit_data_destory(exit_data[i]); } test_free(TEST_MODULE_BCM, exit_data); - test_threads_destory(threads); + test_threads_destory(&test_info, threads); test_queue_destory(&q); bbq_memory_info(); test_memory_info(); diff --git a/perf/benchmark/bcm_loadconfig.c b/perf/benchmark/bcm_loadconfig.c index 94566f6..f285747 100644 --- a/perf/benchmark/bcm_loadconfig.c +++ b/perf/benchmark/bcm_loadconfig.c @@ -1,18 +1,18 @@ /* * @Author: liuyu - * @LastEditTime: 2024-06-06 23:54:46 + * @LastEditTime: 2024-06-11 18:05:56 * @Email: liuyu@geedgenetworks.com * @Describe: TODO */ -#include #include "bbq.h" #include "iniparser.h" #include "test_mix.h" +#include -int test_load_config(const char* config, const char* ring_type, uint32_t burst_cnt, test_cfg* cfg) { +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); - dictionary* ini = iniparser_load(config); + dictionary *ini = iniparser_load(config); if (ini == NULL) { return -1; } @@ -21,11 +21,11 @@ int test_load_config(const char* config, const char* ring_type, uint32_t burst_c cfg->base.name[sizeof(cfg->base.name) - 1] = '\0'; // 获取键值 - char* introduce = (char*)iniparser_getstring(ini, "base:introduce", "none"); + char *introduce = (char *)iniparser_getstring(ini, "base:introduce", "none"); strncpy(cfg->base.introduce, introduce, sizeof(cfg->base.introduce) - 1); - cfg->base.introduce[sizeof(cfg->base.introduce) - 1] = '\0'; // 手工写上 \0 + cfg->base.introduce[sizeof(cfg->base.introduce) - 1] = '\0'; // 手工写上 \0 cfg->base.cores_cnt = iniparser_getint(ini, "base:cores_cnt", 0); - char* workload = (char*)iniparser_getstring(ini, "ring:workload", "unknown"); + char *workload = (char *)iniparser_getstring(ini, "ring:workload", "unknown"); cfg->ring.workload = test_workload_str2enum(workload); cfg->ring.entries_cnt = iniparser_getuint64(ini, "ring:entries_cnt", 0); cfg->ring.producer_cnt = iniparser_getint(ini, "ring:producer_cnt", 0); @@ -40,10 +40,6 @@ int test_load_config(const char* config, const char* ring_type, uint32_t burst_c BBQ_ERR_LOG("unknown ring type:%d", cfg->ring.ring_type); return -1; } - - cfg->run.running = true; - cfg->run.thread_start = ATOMIC_VAR_INIT(0); - cfg->run.producer_exit = ATOMIC_VAR_INIT(0); cfg->ring.burst_cnt = burst_cnt; if (cfg->ring.ring_type == TEST_RING_TYPE_RMIND) { @@ -59,6 +55,11 @@ int test_load_config(const char* config, const char* ring_type, uint32_t burst_c } } + 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); + 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); diff --git a/perf/benchmark/config/compare/general/case1_simple_spsc.ini b/perf/benchmark/config/compare/general/case1_simple_spsc.ini index 19bb059..f0ef942 100644 --- a/perf/benchmark/config/compare/general/case1_simple_spsc.ini +++ b/perf/benchmark/config/compare/general/case1_simple_spsc.ini @@ -10,5 +10,5 @@ consumer_cnt = 1 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file diff --git a/perf/benchmark/config/compare/general/case2_simple_spmc.ini b/perf/benchmark/config/compare/general/case2_simple_spmc.ini index ca05962..f726eff 100644 --- a/perf/benchmark/config/compare/general/case2_simple_spmc.ini +++ b/perf/benchmark/config/compare/general/case2_simple_spmc.ini @@ -10,5 +10,5 @@ consumer_cnt = 4 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 diff --git a/perf/benchmark/config/compare/general/case3_simple_mpsc.ini b/perf/benchmark/config/compare/general/case3_simple_mpsc.ini index 4f3d4fa..071bb4f 100644 --- a/perf/benchmark/config/compare/general/case3_simple_mpsc.ini +++ b/perf/benchmark/config/compare/general/case3_simple_mpsc.ini @@ -10,5 +10,5 @@ consumer_cnt = 1 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file diff --git a/perf/benchmark/config/compare/general/case4_complex_spmc.ini b/perf/benchmark/config/compare/general/case4_complex_spmc.ini index 70764bc..c01f0bc 100644 --- a/perf/benchmark/config/compare/general/case4_complex_spmc.ini +++ b/perf/benchmark/config/compare/general/case4_complex_spmc.ini @@ -10,5 +10,5 @@ consumer_cnt = 4 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file diff --git a/perf/benchmark/config/compare/general/case5_complex_mpsc.ini b/perf/benchmark/config/compare/general/case5_complex_mpsc.ini index 05a1fb0..cea87e1 100644 --- a/perf/benchmark/config/compare/general/case5_complex_mpsc.ini +++ b/perf/benchmark/config/compare/general/case5_complex_mpsc.ini @@ -10,5 +10,5 @@ consumer_cnt = 1 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file diff --git a/perf/benchmark/config/compare/general/case6_simple_mp0c.ini b/perf/benchmark/config/compare/general/case6_simple_mp0c.ini index 50f91b5..61daab1 100644 --- a/perf/benchmark/config/compare/general/case6_simple_mp0c.ini +++ b/perf/benchmark/config/compare/general/case6_simple_mp0c.ini @@ -10,5 +10,5 @@ consumer_cnt = 0 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file diff --git a/perf/benchmark/config/compare/general/case7_simple_0pmc.ini b/perf/benchmark/config/compare/general/case7_simple_0pmc.ini index 5652c21..26d3d34 100644 --- a/perf/benchmark/config/compare/general/case7_simple_0pmc.ini +++ b/perf/benchmark/config/compare/general/case7_simple_0pmc.ini @@ -10,5 +10,5 @@ consumer_cnt = 4 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file diff --git a/perf/benchmark/config/compare/general/case8_simple_mpmc.ini b/perf/benchmark/config/compare/general/case8_simple_mpmc.ini index a365cd0..6b24144 100644 --- a/perf/benchmark/config/compare/general/case8_simple_mpmc.ini +++ b/perf/benchmark/config/compare/general/case8_simple_mpmc.ini @@ -10,5 +10,5 @@ consumer_cnt = 4 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file diff --git a/perf/benchmark/config/compare/general/case9_simple_mpmc_overcore.ini b/perf/benchmark/config/compare/general/case9_simple_mpmc_overcore.ini index 4de4b36..9e8066a 100644 --- a/perf/benchmark/config/compare/general/case9_simple_mpmc_overcore.ini +++ b/perf/benchmark/config/compare/general/case9_simple_mpmc_overcore.ini @@ -10,5 +10,5 @@ consumer_cnt = 16 ;消费者个数 [run] - run_time = 5 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file diff --git a/perf/benchmark/config/compare/perf/perf_case1_simple_spsc.ini b/perf/benchmark/config/compare/perf/perf_case1_simple_spsc.ini index f59ec9b..4a04782 100644 --- a/perf/benchmark/config/compare/perf/perf_case1_simple_spsc.ini +++ b/perf/benchmark/config/compare/perf/perf_case1_simple_spsc.ini @@ -10,5 +10,5 @@ consumer_cnt = 1 ;消费者个数 [run] - run_time = 0 ; 整体运行的秒数,大于0生效 + 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 index 8bc370f..784dec2 100644 --- a/perf/benchmark/config/compare/perf/perf_case2_simple_mpmc.ini +++ b/perf/benchmark/config/compare/perf/perf_case2_simple_mpmc.ini @@ -10,5 +10,5 @@ consumer_cnt = 4 ;消费者个数 [run] - run_time = 0 ; 整体运行的秒数,大于0生效 + 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 index 3392b83..c488a27 100644 --- a/perf/benchmark/config/compare/perf/perf_case3_simple_spmp.ini +++ b/perf/benchmark/config/compare/perf/perf_case3_simple_spmp.ini @@ -10,5 +10,5 @@ consumer_cnt = 4 ;消费者个数 [run] - run_time = 0 ; 整体运行的秒数,大于0生效 + 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 index 945ed87..e9b7bdc 100644 --- a/perf/benchmark/config/compare/perf/perf_case4_simple_mpsc.ini +++ b/perf/benchmark/config/compare/perf/perf_case4_simple_mpsc.ini @@ -10,5 +10,5 @@ consumer_cnt = 1 ;消费者个数 [run] - run_time = 0 ; 整体运行的秒数,大于0生效 + run_time = 10 ; 整体运行的秒数,大于0生效 run_ok_times = 0 ;成功入队/出队次数,大于0生效。 \ No newline at end of file -- cgit v1.2.3