diff options
| author | liuyu <[email protected]> | 2024-07-07 22:55:37 -0400 |
|---|---|---|
| committer | liuyu <[email protected]> | 2024-07-07 22:55:37 -0400 |
| commit | ee1cbf37fc0c08895ed70723029bfbce5f68c060 (patch) | |
| tree | c6437570be6a0b9e2fa4797dbcb158eb260766db /perf/benchmark | |
| parent | d122b40e7633d24ea832175a8339324c9f43beaa (diff) | |
Diffstat (limited to 'perf/benchmark')
| -rw-r--r-- | perf/benchmark/CMakeLists.txt | 21 | ||||
| -rw-r--r-- | perf/benchmark/bcm_benchmark.c | 153 | ||||
| -rw-r--r-- | perf/benchmark/bcm_loadconfig.c | 91 | ||||
| -rw-r--r-- | perf/benchmark/bcm_queue.c | 187 | ||||
| -rw-r--r-- | perf/benchmark/bcm_queue.h | 10 | ||||
| -rwxr-xr-x | perf/benchmark/benchmark.sh | 107 | ||||
| -rw-r--r-- | perf/benchmark/config/bbq_debug/debug.ini | 15 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case1_simple_spsc.ini | 14 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case2_simple_spmc.ini | 14 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case3_simple_mpsc.ini | 14 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case4_complex_spmc.ini | 14 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case5_complex_mpsc.ini | 14 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case6_simple_mp0c.ini | 14 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case7_simple_0pmc.ini | 14 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case8_simple_mpmc.ini | 14 | ||||
| -rw-r--r-- | perf/benchmark/config/compare/case9_simple_mpmc_overcore.ini | 14 |
16 files changed, 710 insertions, 0 deletions
diff --git a/perf/benchmark/CMakeLists.txt b/perf/benchmark/CMakeLists.txt new file mode 100644 index 0000000..323240b --- /dev/null +++ b/perf/benchmark/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.0) +project(BBQ_BENCHMARK) + +# 搜索当前cmake文件所在目录下的c文件 +file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.c") +file(GLOB SRC_BBQ_UT_FUNC_LIST "${UT_BBQ_FUNC_DIR}/*.c") +list(APPEND SRC_LIST ${SRC_BBQ_UT_FUNC_LIST}) + +# 指定可执行文件输出路径 +set(EXECUTABLE_OUTPUT_PATH ${EXEC_PATH}) + +add_executable(benchmark ${SRC_LIST}) # 添加可执行程序 +target_link_libraries(benchmark dl iniparser pthread rte_ring rte_eal rte_kvargs rte_telemetry rmind_ringbuf bbq m) # 链接库 +#target_link_libraries(benchmark dl iniparser pthread dpdk rmind_ringbuf bbq m) # 链接库 + +add_custom_command( + TARGET benchmark POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/benchmark.sh + ${EXECUTABLE_OUTPUT_PATH}/benchmark.sh +) diff --git a/perf/benchmark/bcm_benchmark.c b/perf/benchmark/bcm_benchmark.c new file mode 100644 index 0000000..5a7db7a --- /dev/null +++ b/perf/benchmark/bcm_benchmark.c @@ -0,0 +1,153 @@ +/* + * @Author: liuyu + * @LastEditTime: 2024-07-07 21:19:02 + * @Email: [email protected] + * @Describe: TODO + */ +#include "bbq.h" +#include "bcm_queue.h" +#include "iniparser.h" +#include "ut_bbq_func.h" +#include <pthread.h> +#include <stdatomic.h> +#include <stdlib.h> +#include <string.h> +#include <sys/prctl.h> +#include <unistd.h> + +void bcm_report_printf(struct ut_cfg *cfg, struct ut_merge_data *data, struct ut_exit_data **raw_data, uint32_t thread_cnt, enum ut_thread_type ttype) { + char name[10] = {0}; + double latency_ns = 0; + double throughput = 0; + + printf("\n---------%s---------\n", ttype == UT_THREAD_PRODUCER ? "生产者" : "消费者"); + double use_time = ut_clock_time_to_double(&data->use_time); + printf("执行时间 : %lf 秒\n", use_time); + printf("执行次数 : %lu (burst=%u)\n", data->run_times, cfg->ring.burst_cnt); + printf("成功%s : %lu\n", ttype == UT_THREAD_PRODUCER ? "入队" : "出队", data->ok_cnt); + printf("数据错误次数 : %lu\n", data->data_error_cnt); + + // 同时有生产者、消费者时才输出 + if (cfg->ring.producer_cnt > 0 && cfg->ring.consumer_cnt > 0) { + throughput = data->ok_cnt / use_time; + printf("吞吐 :%.0lf/s (%e/s)\n", throughput, throughput); + + // 多生产者单消费者 或 单生产者多消费才输出 + if ((cfg->ring.producer_cnt == 1 && cfg->ring.consumer_cnt > 1) || + (cfg->ring.producer_cnt > 1 && cfg->ring.consumer_cnt == 1)) { + for (uint32_t i = 0, bbq_head_idx = 1; i < thread_cnt; i++) { + if (raw_data[i]->arg->ttype == ttype) { + struct ut_metric tmp_time = ut_clock_time_sub(raw_data[i]->metric_end, raw_data[i]->metric_start); + throughput = raw_data[i]->ok_cnt / ut_clock_time_to_double(&tmp_time); + printf(" %s-%d 吞吐 :%.0lf/s (%e/s)", name, bbq_head_idx, throughput, throughput); + bbq_head_idx++; + } + } + } + + if (ttype == UT_THREAD_CONSUMER && cfg->ring.workload == UT_WORKLOAD_COMPLEX) { + latency_ns = data->latency_ns * 1.0 / data->ok_cnt; + printf("数据延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); + } + + latency_ns = data->op_ok_latency_ns * 1.0 / data->ok_cnt; + printf("操作延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); + } else { + latency_ns = data->op_err_latency_ns * 1.0 / (data->run_times - data->ok_cnt); + if (ttype == UT_THREAD_PRODUCER) { + printf("满队入队操作延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); + } else { + printf("空队出队操作延迟 :%.0lf 纳秒 (%e)\n", latency_ns, latency_ns); + } + } +} + +void bcm_report_generate(struct ut_cfg *cfg, struct ut_exit_data **exit_data, uint32_t thread_cnt) { + // ut_report report; + + struct ut_merge_s merge = {0}; + ut_merge_all_data(exit_data, thread_cnt, &merge); + + printf("ring类型: %s\n", ut_ring_type_enum2str(cfg->ring.ring_type)); + printf("简介: %s\n", cfg->base.introduce); + printf("配置: %s\n", cfg->base.name); + if (cfg->ring.producer_cnt > 0) { + bcm_report_printf(cfg, &merge.producer, exit_data, thread_cnt, UT_THREAD_PRODUCER); + } + + if (cfg->ring.consumer_cnt > 0) { + bcm_report_printf(cfg, &merge.consumer, exit_data, thread_cnt, UT_THREAD_CONSUMER); + } + + if (cfg->ring.producer_cnt > 0 && cfg->ring.consumer_cnt > 0) { + printf("生产消费个数验证: %s\n", merge.consumer.ok_cnt == merge.producer.ok_cnt ? "相等" : "不等!!!!!!!!!"); + } +} + +int main(int argc, char *argv[]) { + char *config; + char *ring_type; + uint32_t burst_cnt = 0; + + if (argc == 4) { + config = argv[1]; + ring_type = argv[2]; + burst_cnt = strtoul(argv[3], NULL, 0); + if (burst_cnt <= 0) { + burst_cnt = 1; + } + } else { + config = "/root/code/c/bbq/perf/benchmark/config/compare/case1_simple_spsc.ini"; + ring_type = "dpdk"; + burst_cnt = 16; + UT_ERR_LOG("use default config, ringt_type:%s burst:%u config:%s argc:%d", ring_type, burst_cnt, config, argc); + } + + char thread_name[128] = {0}; + snprintf(thread_name, sizeof(thread_name), "main:%lu", pthread_self()); + prctl(PR_SET_NAME, thread_name); + + // 加载配置 + struct ut_info_s info; + if (ut_load_config(config, ring_type, burst_cnt, &info.cfg) != 0) { + UT_ERR_LOG("load config error"); + return -1; + } + + // 队列初始化 + int ret = -1; + struct ut_queue q; + ret = bcm_queue_init(&info.cfg, &q); + if (ret != 0) { + UT_ERR_LOG("init failed :%d", ret); + return ret; + } + + // 创建线程 + pthread_t *threads = ut_threads_create(&info, &q); + if (threads == NULL) { + UT_ERR_LOG("pthread_arr is NULL"); + return ret; + } + + // 等待所有线程完成,回收数据 + uint32_t thread_cnt = info.cfg.ring.producer_cnt + info.cfg.ring.consumer_cnt; + struct ut_exit_data **exit_data = (struct ut_exit_data **)ut_malloc(UT_MODULE_BCM, sizeof(struct ut_exit_data **) * (thread_cnt)); + uint32_t i = 0; + + ut_wait_all_threads_exit(&info, thread_cnt, threads, exit_data); + + // 生成benchmark报告 + bcm_report_generate(&info.cfg, exit_data, thread_cnt); + + // 回收、释放数据 + for (i = 0; i < thread_cnt; i++) { + ut_exit_data_destory(exit_data[i]); + } + ut_free(UT_MODULE_BCM, exit_data); + ut_threads_destory(&info, threads); + ut_queue_destory(&q); + ut_memory_counter_print(); + + return 0; +}
\ No newline at end of file diff --git a/perf/benchmark/bcm_loadconfig.c b/perf/benchmark/bcm_loadconfig.c new file mode 100644 index 0000000..68f7bcc --- /dev/null +++ b/perf/benchmark/bcm_loadconfig.c @@ -0,0 +1,91 @@ +/* + * @Author: liuyu + * @LastEditTime: 2024-07-07 22:13:33 + * @Email: [email protected] + * @Describe: TODO + */ +#include "bbq.h" +#include "iniparser.h" +#include "ut_bbq_func.h" + +#include <string.h> + +int ut_load_config(const char *config, const char *ring_type, uint32_t burst_cnt, struct ut_cfg *cfg) { + int ret = 0; + // 加载配置 + UT_INFO_LOG("load config:%s", config); + dictionary *ini = iniparser_load(config); + if (ini == NULL) { + return -1; + } + + strncpy(cfg->base.name, config, sizeof(cfg->base.name) - 1); + cfg->base.name[sizeof(cfg->base.name) - 1] = '\0'; + + // 获取键值 + const char *introduce = 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 + const char *cores = iniparser_getstring(ini, "base:cores", "unknown"); + ret = sscanf(cores, "%hu-%hu", &cfg->base.core_begin, &cfg->base.core_end); + if (ret != 2) { + UT_ERR_LOG("cores error: %s", cores); + return -1; + } + + const char *workload = iniparser_getstring(ini, "ring:workload", "unknown"); + cfg->ring.workload = ut_workload_str2enum(workload); + cfg->ring.entries_cnt = iniparser_getuint64(ini, "ring:entries_cnt", 0); + cfg->ring.producer_cnt = iniparser_getint(ini, "ring:producer_cnt", 0); + cfg->ring.consumer_cnt = iniparser_getint(ini, "ring:consumer_cnt", 0); + cfg->ring.block_count = iniparser_getint(ini, "ring:block_count", 0); + cfg->run.run_ok_times = iniparser_getint(ini, "run:run_ok_times", 0); + cfg->run.run_time = iniparser_getuint64(ini, "run:run_time", 0); + + // 设置ring_type + cfg->ring.ring_type = ut_ring_type_str2enum(ring_type); + if (cfg->ring.ring_type >= UT_RING_TYPE_MAX) { + UT_ERR_LOG("unknown ring type:%d", cfg->ring.ring_type); + return -1; + } + cfg->ring.burst_cnt = burst_cnt; + + if (cfg->ring.ring_type == UT_RING_TYPE_RMIND) { + // rmind仅支持1个消费者,仅支持burst方式 + if (cfg->ring.consumer_cnt > 1) { + UT_ERR_LOG("ring type:%s only support single consumer", UT_RING_TYPE_RMIND_STR); + return -1; + } + + if (cfg->ring.burst_cnt <= 1) { + UT_ERR_LOG("ring type:%s only support burst_cnt > 1 !", UT_RING_TYPE_RMIND_STR); + return -1; + } + + if (cfg->ring.workload == UT_WORKLOAD_COMPLEX) { + UT_ERR_LOG("ring type:%s only support simple workload !", UT_RING_TYPE_RMIND_STR); + return -1; + } + } + + if (cfg->run.run_time == 0 && cfg->run.run_ok_times == 0) { + UT_ERR_LOG("At least one of run_time or run_ok_times is not 0"); + return -1; + } + + UT_INFO_LOG("introduce:%s", cfg->base.introduce); + UT_INFO_LOG("cores:%u-%u", cfg->base.core_begin, cfg->base.core_end); + UT_INFO_LOG("workload:%s(%u)", workload, cfg->ring.workload); + UT_INFO_LOG("entries_cnt:%lu", cfg->ring.entries_cnt); + UT_INFO_LOG("producer_cnt:%u", cfg->ring.producer_cnt); + UT_INFO_LOG("consumer_cnt:%u", cfg->ring.consumer_cnt); + UT_INFO_LOG("block_count:%u", cfg->ring.block_count); + UT_INFO_LOG("run_ok_times:%lu", cfg->run.run_ok_times); + UT_INFO_LOG("run_time:%lu", cfg->run.run_time); + UT_INFO_LOG("ring_type:%s(%u)", ring_type, cfg->ring.ring_type); + UT_INFO_LOG("burst_cnt:%u", burst_cnt); + + // 释放dictionary对象 + iniparser_freedict(ini); + return 0; +}
\ No newline at end of file diff --git a/perf/benchmark/bcm_queue.c b/perf/benchmark/bcm_queue.c new file mode 100644 index 0000000..b116f25 --- /dev/null +++ b/perf/benchmark/bcm_queue.c @@ -0,0 +1,187 @@ +/* + * @Author: liuyu + * @LastEditTime: 2024-07-07 20:52:05 + * @Email: [email protected] + * @Describe: TODO + */ +#include "bcm_queue.h" +#include "ringbuf.h" + +static __rte_always_inline unsigned int +bcm_dpdk_ring_enqueue_burst(struct rte_ring *r, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed) { + UT_AVOID_WARNING(thread_idx); + int ret = 0; + + if (wait_consumed) { + unsigned int free_space = 0; + ret = rte_ring_enqueue_burst(r, (void *const *)obj_table, n, &free_space); + *wait_consumed = r->size - free_space - 1; + } else { + ret = rte_ring_enqueue_burst(r, (void *const *)obj_table, n, NULL); + } + + return ret; +} + +int ut_queue_init_dpdk(struct ut_cfg *cfg, struct ut_queue *q) { + /* generate eal parameters */ + const char *eal_args[] = {"bcm_dpdk", "-n", "4", "--proc-type", "auto", "--no-huge", "-m", "2048"}; + if (rte_eal_init(RTE_DIM(eal_args), (char **)eal_args) < 0) { + return -1; + } + + q->ring_type = UT_RING_TYPE_DPDK; + unsigned int flags = 0; + if (cfg->ring.producer_cnt <= 1) { + flags |= RING_F_SP_ENQ; + } else { + flags |= RING_F_MP_RTS_ENQ; + } + + if (cfg->ring.consumer_cnt <= 1) { + flags |= RING_F_SC_DEQ; + } else { + flags |= RING_F_MC_RTS_DEQ; + } + + q->ring = (void *)rte_ring_create("dpdk_ring", cfg->ring.entries_cnt, rte_socket_id(), flags); + if (q->ring == NULL) { + return BBQ_ERR_INPUT_NULL; + } + + q->ring_free_f = (ut_ring_free_f)rte_ring_free; + q->enqueue_f = (ut_ring_enqueue_f)rte_ring_enqueue; + q->dequeue_f = (ut_ring_dequeue_f)rte_ring_dequeue; + q->enqueue_burst_f = (ut_enqueue_burst_f)bcm_dpdk_ring_enqueue_burst; + q->dequeue_burst_f = (ut_dequeue_burst_f)rte_ring_dequeue_burst; + + return BBQ_OK; +} + +unsigned char *rmind_buf; +uint16_t worker_cnt; +ringbuf_worker_t **rmind_workers; + +void ut_queue_free_rmind(void *ring) { + for (uint16_t i = 0; i < worker_cnt; i++) { + ringbuf_unregister((ringbuf_t *)ring, rmind_workers[i]); + } + + ut_free(UT_MODULE_RMIND, rmind_workers); + ut_free(UT_MODULE_RMIND, rmind_buf); + ut_free(UT_MODULE_RMIND, ring); +} + +uint32_t ut_enqueue_burst_rmind(void *ring, void **obj_table, uint32_t n, uint16_t thread_idx, uint32_t *wait_consumed) { + UT_AVOID_WARNING(wait_consumed); + uint32_t cnt = 0; + int ret = 0; + size_t off = 0; + void *obj = NULL; + ringbuf_worker_t *w = (ringbuf_worker_t *)rmind_workers[thread_idx]; + size_t len = sizeof(uintptr_t); + + for (cnt = 0; cnt < n; cnt++) { + obj = obj_table[cnt]; + uintptr_t uptr = (uintptr_t)obj; + + if ((ret = ringbuf_acquire(ring, w, len)) != -1) { + off = (size_t)ret; + memcpy(&rmind_buf[off], &uptr, len); + ringbuf_produce(ring, w); + } else { + break; + } + } + + return cnt; +} + +uint32_t ut_dequeue_burst_rmind(void *ring, void *obj_table, uint32_t n, uint32_t *wait_consumed) { + UT_AVOID_WARNING(n); + UT_AVOID_WARNING(wait_consumed); + size_t len = 0; + size_t off = 0; + size_t per_size = sizeof(void *); + void **table = (void **)obj_table; + + if ((len = ringbuf_consume(ring, &off)) != 0) { + size_t rem = len; + size_t i = 0; + + while (rem) { + uintptr_t *data = (uintptr_t *)(&rmind_buf[off]); + table[i] = (void *)(*data); + i++; + off += per_size; + rem -= sizeof(void *); + } + ringbuf_release(ring, len); + return i; + } + + return 0; +} + +int ut_queue_init_rmind(struct ut_cfg *cfg, struct ut_queue *q) { + static size_t ringbuf_obj_size; + worker_cnt = cfg->ring.producer_cnt + cfg->ring.consumer_cnt; + + ringbuf_get_sizes(worker_cnt, &ringbuf_obj_size, NULL); + ringbuf_t *r = ut_malloc(UT_MODULE_RMIND, ringbuf_obj_size); + if (r == NULL) { + exit(-1); + } + + size_t buf_size = sizeof(void *) * cfg->ring.entries_cnt; + rmind_buf = ut_malloc(UT_MODULE_RMIND, buf_size); + if (rmind_buf == NULL) { + exit(-1); + } + ringbuf_setup(r, worker_cnt, buf_size); + + rmind_workers = ut_malloc(UT_MODULE_RMIND, sizeof(*rmind_workers) * worker_cnt); + if (rmind_workers == NULL) { + exit(-1); + } + for (uint32_t i = 0; i < worker_cnt; i++) { + rmind_workers[i] = ringbuf_register(r, i); + if (rmind_workers[i] == NULL) { + exit(-1); + } + } + + q->ring = r; + q->ring_free_f = (ut_ring_free_f)ut_queue_free_rmind; + q->enqueue_f = NULL; + q->dequeue_f = NULL; + q->enqueue_burst_f = (ut_enqueue_burst_f)ut_enqueue_burst_rmind; + q->dequeue_burst_f = (ut_dequeue_burst_f)ut_dequeue_burst_rmind; + + return 0; +} + +int bcm_queue_init(struct ut_cfg *cfg, struct ut_queue *q) { + if (cfg == NULL || q == NULL) { + return BBQ_ERR_INPUT_NULL; + } + + memset(q, 0, sizeof(*q)); + int ret = -1; + q->ring_type = cfg->ring.ring_type; + switch (q->ring_type) { + case UT_RING_TYPE_DPDK: + ret = ut_queue_init_dpdk(cfg, q); + break; + case UT_RING_TYPE_BBQ: + ret = ut_queue_init_bbq(cfg, q); + break; + case UT_RING_TYPE_RMIND: + ret = ut_queue_init_rmind(cfg, q); + break; + default: + return BBQ_ERR; + } + + return ret; +} diff --git a/perf/benchmark/bcm_queue.h b/perf/benchmark/bcm_queue.h new file mode 100644 index 0000000..11006e4 --- /dev/null +++ b/perf/benchmark/bcm_queue.h @@ -0,0 +1,10 @@ +/* + * @Author: liuyu + * @LastEditTime: 2024-07-07 21:18:56 + * @Email: [email protected] + * @Describe: TODO + */ +#include "rte_ring.h" +#include "ut_bbq_func.h" + +extern int bcm_queue_init(struct ut_cfg *cfg, struct ut_queue *q);
\ No newline at end of file diff --git a/perf/benchmark/benchmark.sh b/perf/benchmark/benchmark.sh new file mode 100755 index 0000000..abde645 --- /dev/null +++ b/perf/benchmark/benchmark.sh @@ -0,0 +1,107 @@ +#!/bin/bash +### +# @Author: liuyu + # @LastEditTime: 2024-06-30 21:43:01 +# @Email: [email protected] +# @Describe: 运行性能测试的脚本 +### + +ring_type_arr=("bbq" "dpdk" "rmind") +burst_arr=("32" "16" "8" "1") + +# 检查参数数量 +if [ "$#" -ne 3 ]; then + echo "Usage: $0 <path to benchmark> <path to config file or directory> <ring type>" + exit 1 +fi + +# 获取参数值 +BENCHMARK_PATH=$1 +CONFIG_DIR=$2 +RING_TYPE=$3 + +function exec_benchmark_ring_type() { + local ini="$1" + local ring="$2" + local log_file=$3 + local burst=$4 + + # 如果以perf开头的配置文件,还要执行perf统计 + if [[ $(basename "$ini") == perf* ]]; then + echo "skip perf*" + # echo perf stat -e L1-dcache-loads,L1-dcache-load-misses "$BENCHMARK_PATH" "$ini" "$ring" "$BURST_CNT" + # perf stat -e L1-dcache-loads,L1-dcache-load-misses "$BENCHMARK_PATH" "$ini" "$ring" "$BURST_CNT" + else + "$BENCHMARK_PATH" "$ini" "$ring" "$burst" 2>&1 | tee -a "$log_file" + fi +} + +function exec_benchmark() { + # 提取配置文件名(不带路径) + local INI_FILE=$1 + local log_file=$2 + local burst=$3 + + # 执行benchmark命令并传递配置文件作为参数 + echo "Executing benchmark with $INI_FILE" + + # 使用所有ring_type + if [ "$RING_TYPE" == "all" ]; then + for ring_type_tmp in "${ring_type_arr[@]}"; do + echo start ring:"$ring_type_tmp" + exec_benchmark_ring_type "$INI_FILE" "$ring_type_tmp" "$log_file" "$burst" + done + else + exec_benchmark_ring_type "$INI_FILE" "$RING_TYPE" "$log_file" "$burst" + fi +} + +# 检查benchmark文件是否存在且可执行 +if [ ! -x "$BENCHMARK_PATH" ]; then + echo "Error: Benchmark executable '$BENCHMARK_PATH' does not exist or is not executable." + exit 1 +fi + +# 检查配置文件目录是否存在 +if [ ! -e "$CONFIG_DIR" ]; then + echo "Error: Config directory '$CONFIG_DIR' does not exist." + exit 1 +fi + +# 创建报告目录 +timestamp=$(date +"%Y%m%d_%H%M%S") +folder_path="/tmp/bbq/$timestamp" +rm -rf "$folder_path" +mkdir -p "$folder_path" + +# 开始时间 +start_time=$(date +%s) + +for burst in "${burst_arr[@]}"; do + burst_dir="$folder_path"/burst_"$burst" + mkdir -p "$burst_dir" + for i in {1..3}; do + echo ======"$i"======== + report_path="$burst_dir"/report_"$i".txt + if [[ -f "$CONFIG_DIR" ]]; then + # 如果是文件,直接执行 + exec_benchmark "$CONFIG_DIR" "$report_path" "$burst" + else + # 使用 find 命令递归地搜索所有的 .ini 文件,并按文件名排序 + find "$CONFIG_DIR" -type f -name "*.ini" -print0 | sort -z | while IFS= read -r -d '' INI_FILE; do + if [ -f "$INI_FILE" ]; then + exec_benchmark "$INI_FILE" "$report_path" "$burst" + fi + done + fi + + sleep 1 + done +done + +# 结束时间 +end_time=$(date +%s) +# 计算时间差(秒) +runtime=$((end_time - start_time)) +# 输出运行时间 +echo "done, use $runtime second" diff --git a/perf/benchmark/config/bbq_debug/debug.ini b/perf/benchmark/config/bbq_debug/debug.ini new file mode 100644 index 0000000..cead690 --- /dev/null +++ b/perf/benchmark/config/bbq_debug/debug.ini @@ -0,0 +1,15 @@ +[base] + introduce = "bbq简单负载下,多生产者、单消费者 block=0" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "simple" ;负载模式 simple/complex + entries_cnt = 8 ;ring初始化时分配entry的个数 + block_count = 2 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 4 ;生产者个数 + consumer_cnt = 1 ;消费者个数 + +[run] + run_time = 10 ; 整体运行的秒数,大于0生效 + enqueue_cnt = 0 ;每个线程入队次数,大于0生效 + dequeue_cnt = 0 ;每个线程出队次数,大于0生效
\ No newline at end of file diff --git a/perf/benchmark/config/compare/case1_simple_spsc.ini b/perf/benchmark/config/compare/case1_simple_spsc.ini new file mode 100644 index 0000000..e1ee087 --- /dev/null +++ b/perf/benchmark/config/compare/case1_simple_spsc.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case1 简单负载下,单生产者、单消费者 吞吐测试" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "simple" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 1 ;生产者个数 + consumer_cnt = 1 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/case2_simple_spmc.ini b/perf/benchmark/config/compare/case2_simple_spmc.ini new file mode 100644 index 0000000..8216381 --- /dev/null +++ b/perf/benchmark/config/compare/case2_simple_spmc.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case2 简单负载下,单生产者、多消费者 吞吐测试" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "simple" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 1 ;生产者个数 + consumer_cnt = 4 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。 diff --git a/perf/benchmark/config/compare/case3_simple_mpsc.ini b/perf/benchmark/config/compare/case3_simple_mpsc.ini new file mode 100644 index 0000000..3476774 --- /dev/null +++ b/perf/benchmark/config/compare/case3_simple_mpsc.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case3 简单负载下,多生产者、单消费者 吞吐测试" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "simple" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 4 ;生产者个数 + consumer_cnt = 1 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/case4_complex_spmc.ini b/perf/benchmark/config/compare/case4_complex_spmc.ini new file mode 100644 index 0000000..64e3e41 --- /dev/null +++ b/perf/benchmark/config/compare/case4_complex_spmc.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case4 复杂负载下,单生产者、多消费者 吞吐测试" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "complex" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 1 ;生产者个数 + consumer_cnt = 4 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/case5_complex_mpsc.ini b/perf/benchmark/config/compare/case5_complex_mpsc.ini new file mode 100644 index 0000000..2404649 --- /dev/null +++ b/perf/benchmark/config/compare/case5_complex_mpsc.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case5 复杂负载下,多生产者、单消费者 吞吐测试" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "complex" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 4 ;生产者个数 + consumer_cnt = 1 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/case6_simple_mp0c.ini b/perf/benchmark/config/compare/case6_simple_mp0c.ini new file mode 100644 index 0000000..62325e4 --- /dev/null +++ b/perf/benchmark/config/compare/case6_simple_mp0c.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case6 简单负载下,多生产者、无消费者,测试满队入队操作时延" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "simple" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 4 ;生产者个数 + consumer_cnt = 0 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/case7_simple_0pmc.ini b/perf/benchmark/config/compare/case7_simple_0pmc.ini new file mode 100644 index 0000000..1c5ed2c --- /dev/null +++ b/perf/benchmark/config/compare/case7_simple_0pmc.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case7 简单负载下,无生产者、多消费者,测试空队出队操作时延" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "simple" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 0 ;生产者个数 + consumer_cnt = 4 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/case8_simple_mpmc.ini b/perf/benchmark/config/compare/case8_simple_mpmc.ini new file mode 100644 index 0000000..b5026bb --- /dev/null +++ b/perf/benchmark/config/compare/case8_simple_mpmc.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case8 简单负载下,多生产者、多消费者 吞吐测试" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "simple" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 4 ;生产者个数 + consumer_cnt = 4 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file diff --git a/perf/benchmark/config/compare/case9_simple_mpmc_overcore.ini b/perf/benchmark/config/compare/case9_simple_mpmc_overcore.ini new file mode 100644 index 0000000..b4b304a --- /dev/null +++ b/perf/benchmark/config/compare/case9_simple_mpmc_overcore.ini @@ -0,0 +1,14 @@ +[base] + introduce = "general case9 简单负载下,多生产者、多消费者 线程核心超过已有核心时的吞吐测试" ;测试配置说明 + cores = "20-27" ;测试用核心起止范围 + +[ring] + workload = "simple" ;负载模式 simple/complex + entries_cnt = 4096 ;ring初始化时分配entry的个数 + block_count = 0 ;bbq配置,等于0则表示根据entries_cnt自动计算 + producer_cnt = 16 ;生产者个数 + consumer_cnt = 16 ;消费者个数 + +[run] + run_time = 15 ; 整体运行的秒数,大于0生效 + run_ok_times = 0 ;成功入队/出队次数,大于0生效。
\ No newline at end of file |
