summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bbq/include/bbq.h4
-rw-r--r--bbq/tests/common/test_mix.c19
-rw-r--r--bbq/tests/common/test_mix.h100
-rw-r--r--bbq/tests/common/test_queue.c163
-rw-r--r--bbq/tests/common/test_queue.h15
-rw-r--r--bbq/tests/unittest/ut_data.cc56
-rw-r--r--bbq/tests/unittest/ut_head_cursor.cc86
-rw-r--r--bbq/tests/unittest/ut_mix.cc1
-rw-r--r--perf/CMakeLists.txt2
-rw-r--r--perf/benchmark/CMakeLists.txt2
-rw-r--r--perf/benchmark/bcm_benchmark.c45
-rw-r--r--perf/benchmark/bcm_loadconfig.c23
-rw-r--r--perf/benchmark/config/compare/general/case1_simple_spsc.ini2
-rw-r--r--perf/benchmark/config/compare/general/case2_simple_spmc.ini2
-rw-r--r--perf/benchmark/config/compare/general/case3_simple_mpsc.ini2
-rw-r--r--perf/benchmark/config/compare/general/case4_complex_spmc.ini2
-rw-r--r--perf/benchmark/config/compare/general/case5_complex_mpsc.ini2
-rw-r--r--perf/benchmark/config/compare/general/case6_simple_mp0c.ini2
-rw-r--r--perf/benchmark/config/compare/general/case7_simple_0pmc.ini2
-rw-r--r--perf/benchmark/config/compare/general/case8_simple_mpmc.ini2
-rw-r--r--perf/benchmark/config/compare/general/case9_simple_mpmc_overcore.ini2
-rw-r--r--perf/benchmark/config/compare/perf/perf_case1_simple_spsc.ini2
-rw-r--r--perf/benchmark/config/compare/perf/perf_case2_simple_mpmc.ini2
-rw-r--r--perf/benchmark/config/compare/perf/perf_case3_simple_spmp.ini2
-rw-r--r--perf/benchmark/config/compare/perf/perf_case4_simple_mpsc.ini2
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: [email protected]
- * @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 <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
@@ -18,6 +17,7 @@
#ifndef __cplusplus
// C
+#include <stdatomic.h>
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 <pthread.h>
#include <string.h>
#include <sys/time.h>
@@ -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
* @Describe: TODO
*/
#ifndef _TEST_MIX_H_
#define _TEST_MIX_H_
-#include <stdatomic.h>
+#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
+#ifndef __cplusplus
+// C
+#include <stdatomic.h>
+#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<uint32_t> thread_start;
std::atomic<uint32_t> 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
* @Describe: TODO
*/
#include "test_queue.h"
-#include <sys/prctl.h>
-#include <unistd.h>
#include "bbq.h"
#include "test_mix.h"
+#include <sys/prctl.h>
+#include <unistd.h>
-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
* @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
* @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
* @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 <math.h>
-#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
* @Describe: TODO
*/
+#include "bbq.h"
+#include "bcm_queue.h"
+#include "iniparser.h"
+#include "test_mix.h"
+#include "test_queue.h"
#include <pthread.h>
#include <stdatomic.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
-#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
* @Describe: TODO
*/
-#include <string.h>
#include "bbq.h"
#include "iniparser.h"
#include "test_mix.h"
+#include <string.h>
-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