From 97c403b636398eca93c4002bf85a3d554ee59c31 Mon Sep 17 00:00:00 2001 From: wjf-hs Date: Thu, 21 May 2026 16:33:58 +0800 Subject: [PATCH] =?UTF-8?q?chore(perf):=20=E6=80=A7=E8=83=BD=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=96=B0=E5=A2=9Erun=5Fcount=E5=B9=B6=E7=94=A8?= =?UTF-8?q?=E6=B5=8B=E8=AF=95ringbuf=E5=92=8Csegarray=E7=9A=84=E6=80=A7?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E7=9B=B4=E8=A7=82=E7=9C=8B=E5=87=BA=E5=B7=AE?= =?UTF-8?q?=E5=BC=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/PERF.md | 71 ------------------------------------- doc/perf.md | 46 ++++++++++++++++++++++++ include/deque.h | 2 +- include/unicstl_config.h | 2 +- perf/perf.c | 48 +++++++++++++++---------- perf/perf.h | 24 +++++++------ perf/perf_deque.c | 11 +++--- perf/perf_log.c | 2 +- perf/perf_queue.c | 4 +-- perf/perf_ringbuf.c | 76 ++++++++++++++++++++++++++++++++++++++++ perf/perf_segarray.c | 76 ++++++++++++++++++++++++++++++++++++++++ perf/perf_stack.c | 4 +-- run.bat | 4 +-- src/heap.c | 6 +--- 14 files changed, 259 insertions(+), 117 deletions(-) delete mode 100644 doc/PERF.md create mode 100644 doc/perf.md create mode 100644 perf/perf_ringbuf.c create mode 100644 perf/perf_segarray.c diff --git a/doc/PERF.md b/doc/PERF.md deleted file mode 100644 index f9d4706..0000000 --- a/doc/PERF.md +++ /dev/null @@ -1,71 +0,0 @@ - -# performance - -## 性能对比 - -### 测试环境 - -| 测试环境 | 详细信息 | -| --------| -----| -| CPU | Intel(R) Pentium(R) G4560 @ 3.50GHz | -| 内存 | 16GB | -| OS | win10 22H2 | -| gcc | mingw (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 13.2.0 | - - -### 测试方案 -``` -T0: capacity = 1024, obj_size = 256 -T1: capacity = 4096, obj_size = 256 -T2: capacity = 8192, obj_size = 256 -T3: capacity = 1024, obj_size = 4096 -T4: capacity = 4096, obj_size = 4096 -T5: capacity = 8192, obj_size = 4096 -``` - -### 测试对比 -> 这里是总时间,对比意义不大。而且目前都未使用扩容 - -1. 链表实现的栈和队列 - -```bash - function T0 (ms) T1 (ms) T2 (ms) T3 (ms) T4 (ms) T5 (ms) - -------------------- --------- --------- --------- --------- --------- --------- -perf_deque_new() 0.013 0.011 0.008 0.008 0.013 0.014 -perf_deque_push_back() 0.161 0.520 1.011 0.626 2.934 7.444 -perf_deque_pop_back() 0.032 0.172 0.329 0.236 1.478 2.728 -perf_deque_push_front() 0.038 0.162 0.369 0.175 1.019 2.050 -perf_deque_pop_front() 0.037 0.146 0.305 0.220 2.061 2.628 -perf_deque_free() 0.001 0.092 0.187 0.357 1.287 2.694 -perf_stack_new() 0.002 0.001 0.002 0.001 0.001 0.001 -perf_stack_push() 0.271 1.003 1.941 1.967 8.882 16.369 -perf_stack_pop() 0.164 1.183 1.893 0.965 3.717 8.114 -perf_stack_free() 0.000 0.001 0.001 0.002 0.001 0.001 -perf_queue_new() 0.018 0.000 0.000 0.000 0.001 0.002 -perf_queue_push() 0.258 1.020 1.947 1.537 7.774 15.220 -perf_queue_pop() 0.162 0.613 1.050 0.811 3.590 7.070 -perf_queue_free() 0.000 0.000 0.000 0.001 0.001 0.001 -``` - -2. 动态数组实现的栈和队列(这里还不涉及到扩容) - -```bash - function T0 (ms) T1 (ms) T2 (ms) T3 (ms) T4 (ms) T5 (ms) - -------------------- --------- --------- --------- --------- --------- --------- -perf_deque_new() 0.011 0.018 0.015 0.033 0.017 0.017 -perf_deque_push_back() 0.187 0.650 1.216 1.692 2.852 6.202 -perf_deque_pop_back() 0.052 0.219 0.468 0.685 1.332 2.295 -perf_deque_push_front() 0.058 0.262 0.536 0.290 1.155 1.845 -perf_deque_pop_front() 0.055 0.239 0.438 0.427 1.398 2.398 -perf_deque_free() 0.002 0.151 0.286 0.361 2.695 3.049 -perf_stack_new() 0.224 0.013 0.013 0.010 0.014 0.014 -perf_stack_push() 0.036 0.388 0.745 0.801 2.890 6.183 -perf_stack_pop() 0.035 0.244 0.318 0.236 1.109 3.167 -perf_stack_free() 0.002 0.113 0.177 0.408 1.272 2.578 -perf_queue_new() 0.010 0.012 0.007 0.008 0.012 0.014 -perf_queue_push() 0.148 0.377 0.701 0.737 2.955 6.273 -perf_queue_pop() 0.030 0.149 0.271 0.230 1.173 2.338 -perf_queue_free() 0.001 0.094 0.154 0.350 1.273 2.556 -``` - - diff --git a/doc/perf.md b/doc/perf.md new file mode 100644 index 0000000..7c3ff8b --- /dev/null +++ b/doc/perf.md @@ -0,0 +1,46 @@ + +# performance + +## 性能对比 + +### 测试环境 + +| 测试环境 | 详细信息 | +| --------| -----| +| CPU | Intel(R) Pentium(R) G4560 @ 3.50GHz | +| 内存 | 16GB | +| OS | win10 22H2 | +| gcc | mingw (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 13.2.0 | + +### 测试结果 + +1. ringbuf和segarray的性能对比 +``` +T0: obj_size=256, capacity=1024, run_count=1024 +T1: obj_size=256, capacity=8192, run_count=8192 +T2: obj_size=4096, capacity=1024, run_count=1024 +T3: obj_size=4096, capacity=8192, run_count=8192 +T4: obj_size=256, capacity=1024, run_count=100000 +T5: obj_size=256, capacity=8192, run_count=100000 +T6: obj_size=4096, capacity=1024, run_count=100000 +T7: obj_size=4096, capacity=8192, run_count=100000 + + function T0 (us) T1 (us) T2 (us) T3 (us) T4 (us) T5 (us) T6 (us) T7 (us) + -------------------- --------- --------- --------- --------- --------- --------- --------- --------- +perf_segarray_new() 0.008 0.000 0.000 0.000 0.000 0.000 0.000 0.000 +perf_segarray_push_back() 0.215 0.316 0.658 1.038 0.182 0.158 0.795 0.978 +perf_segarray_pop_back() 0.058 0.060 0.231 0.497 0.054 0.056 0.328 0.327 +perf_segarray_free() 0.037 0.026 0.332 0.335 0.022 0.024 0.337 0.308 +perf_segarray_new() 0.001 0.000 0.001 0.000 0.000 0.000 0.000 0.000 +perf_segarray_push_front() 0.180 0.148 1.569 1.952 0.172 0.147 1.685 1.942 +perf_segarray_pop_front() 0.051 0.060 0.242 0.342 0.062 0.061 0.348 0.368 +perf_segarray_free() 0.034 0.023 0.325 0.342 0.026 0.021 0.369 0.306 +perf_ringbuf_new() 0.006 0.002 0.019 0.003 0.000 0.000 0.000 0.000 +perf_ringbuf_push_back() 0.153 0.096 0.983 0.866 0.854 1.060 13.849 14.344 +perf_ringbuf_pop_back() 0.030 0.037 0.273 0.275 0.049 0.054 0.344 0.317 +perf_ringbuf_free() 0.032 0.018 0.393 0.371 0.019 0.026 0.340 0.307 +perf_ringbuf_new() 0.006 0.001 0.022 0.003 0.000 0.000 0.000 0.000 +perf_ringbuf_push_front() 0.138 0.135 2.114 1.941 0.990 1.252 14.603 13.887 +perf_ringbuf_pop_front() 0.039 0.065 0.292 0.365 0.045 0.044 0.516 0.309 +perf_ringbuf_free() 0.000 0.024 0.407 0.408 0.025 0.023 0.605 0.301 +``` diff --git a/include/deque.h b/include/deque.h index 98fde09..286c09a 100644 --- a/include/deque.h +++ b/include/deque.h @@ -16,7 +16,7 @@ #include "segarray.h" // 0.rinfbuf 1.segarray -#define DEQUE_DEFAULT_SELECT 1 +#define DEQUE_DEFAULT_SELECT 0 #if DEQUE_DEFAULT_SELECT == 1 #define DEQUE_RINGBUF 0 diff --git a/include/unicstl_config.h b/include/unicstl_config.h index 8c16a20..8832342 100644 --- a/include/unicstl_config.h +++ b/include/unicstl_config.h @@ -74,7 +74,7 @@ * LOG_ERROR * LOG_NONE */ -#define LOG_LEVEL LOG_DEBUG +#define LOG_LEVEL LOG_NONE /** * @brief diff --git a/perf/perf.c b/perf/perf.c index 99b42db..4887216 100644 --- a/perf/perf.c +++ b/perf/perf.c @@ -1,24 +1,29 @@ /** * @file main.c * @author wenjf (Orig5826@163.com) - * @brief + * @brief * @version 0.1 * @date 2026-05-12 - * + * * @copyright Copyright (c) 2026 - * + * */ #include "perf.h" #include "perf_log.h" +// clang-format off test_obj_t test_plans[PERF_TEST_TIEMS] = { - {.capacity = 1024, .obj_size = 256}, // 1. 小对象 + 少量数据 - {.capacity = 4096, .obj_size = 256}, // 2. 小对象 + 中等数据 - {.capacity = 8192, .obj_size = 256}, // 3. 小对象 + 大量数据 - {.capacity = 1024, .obj_size = 4096}, // 4. 大对象 + 少量数据 - {.capacity = 4096, .obj_size = 4096}, // 5. 大对象 + 中等数据 - {.capacity = 8192, .obj_size = 4096} // 6. 大对象 + 大量数据 + {.obj_size = 256, .capacity = 1024, .run_count = 1024, }, // 1. 小对象 + 少量数据 + {.obj_size = 256, .capacity = 8192, .run_count = 8192, }, // 2. 小对象 + 大量数据 + {.obj_size = 4096, .capacity = 1024, .run_count = 1024, }, // 3. 大对象 + 少量数据 + {.obj_size = 4096, .capacity = 8192, .run_count = 8192, }, // 4. 大对象 + 大量数据 + + {.obj_size = 256, .capacity = 1024, .run_count = 100000, }, // 1. 小对象 + 少量数据 + 扩容 + {.obj_size = 256, .capacity = 8192, .run_count = 100000, }, // 2. 小对象 + 大量数据 + 扩容 + {.obj_size = 4096, .capacity = 1024, .run_count = 100000, }, // 3. 大对象 + 少量数据 + 扩容 + {.obj_size = 4096, .capacity = 8192, .run_count = 100000, }, // 4. 大对象 + 大量数据 + 扩容 }; +// clang-format on test_obj_t g_test_obj; @@ -37,17 +42,19 @@ void perf_deinit(void) perf_log_free(); } -void perf_begin(struct _perf_args* args) +void perf_begin(struct _perf_args *args) { timespec_get(&args->start, TIME_UTC); } -void perf_end(struct _perf_args* args) +void perf_end(struct _perf_args *args) { timespec_get(&args->end, TIME_UTC); args->elapsed = calc_elapsed(args->start, args->end); - perf_log_append(args->name, args->id, args->elapsed * 1000); + // printf("run_count = %zu, elapsed = %.3f ms\n", args->run_count, args->elapsed * 1000); + // perf_log_append(args->name, args->id, args->elapsed * 1000); + perf_log_append(args->name, args->id, args->elapsed * 1000*1000 / args->run_count); } void perf_run_start(size_t id) @@ -56,9 +63,10 @@ void perf_run_start(size_t id) g_test_obj.capacity = test_plans[id].capacity; g_test_obj.obj_size = test_plans[id].obj_size; + g_test_obj.run_count = test_plans[id].run_count; g_test_obj.obj = unicstl_malloc(g_test_obj.capacity); - if(g_test_obj.obj == NULL) + if (g_test_obj.obj == NULL) { log_debug("unicstl_malloc failed"); return; @@ -72,9 +80,10 @@ void perf_run_end(size_t id) void perf_print(void) { - for(size_t i = 0; i < PERF_TEST_TIEMS; i++) + for (size_t i = 0; i < PERF_TEST_TIEMS; i++) { - printf("T%d: capacity = %zu, obj_size = %zu\n", i, test_plans[i].capacity, test_plans[i].obj_size); + printf("T%d: obj_size=%zu, capacity=%zu, run_count=%zu\n", i, + test_plans[i].obj_size, test_plans[i].capacity, test_plans[i].run_count); } printf("\n"); perf_log_print(); @@ -85,9 +94,12 @@ int main(int argc, char *argv[]) { perf_init(); - perf_test_deque(); - perf_test_stack(); - perf_test_queue(); + perf_test_segarray(); + perf_test_ringbuf(); + + // perf_test_deque(); + // perf_test_stack(); + // perf_test_queue(); perf_print(); perf_deinit(); diff --git a/perf/perf.h b/perf/perf.h index a9e123c..c4de73e 100644 --- a/perf/perf.h +++ b/perf/perf.h @@ -24,8 +24,17 @@ struct _perf_args struct timespec start; // [C11] struct timespec end; // [C11] double elapsed; + size_t run_count; }; +typedef struct _test_obj +{ + void *obj; + size_t obj_size; + size_t capacity; + size_t run_count; +}test_obj_t; + /** * @brief run the performance test function * @@ -37,6 +46,7 @@ struct _perf_args .start = {0}, \ .end = {0}, \ .elapsed = 0, \ + .run_count = g_test_obj.run_count,\ };\ perf_begin(&args); \ (func); \ @@ -49,16 +59,7 @@ struct _perf_args perf_run_end(ID); \ }while(0) - -typedef struct _test_obj -{ - void *obj; - size_t obj_size; - size_t capacity; -}test_obj_t; - - -#define PERF_TEST_TIEMS 6 +#define PERF_TEST_TIEMS 8 extern test_obj_t g_test_obj; /** @@ -80,6 +81,9 @@ void perf_print(void); * @brief perf test items * */ +void perf_test_segarray(void); +void perf_test_ringbuf(void); + void perf_test_deque(void); void perf_test_stack(void); void perf_test_queue(void); diff --git a/perf/perf_deque.c b/perf/perf_deque.c index 4ba1eac..13ef6fa 100644 --- a/perf/perf_deque.c +++ b/perf/perf_deque.c @@ -19,7 +19,7 @@ void perf_deque_new(void) void perf_deque_push_back(void) { - for (size_t i = 0; i < g_test_obj.capacity; i++) + for (size_t i = 0; i < g_test_obj.run_count; i++) { deque->push_back(deque, &g_test_obj.obj); } @@ -27,7 +27,7 @@ void perf_deque_push_back(void) void perf_deque_pop_back(void) { - for (size_t i = 0; i < g_test_obj.capacity; i++) + for (size_t i = 0; i < g_test_obj.run_count; i++) { deque->pop_back(deque, &g_test_obj.obj); } @@ -35,7 +35,7 @@ void perf_deque_pop_back(void) void perf_deque_push_front(void) { - for (size_t i = 0; i < g_test_obj.capacity; i++) + for (size_t i = 0; i < g_test_obj.run_count; i++) { deque->push_front(deque, &g_test_obj.obj); } @@ -43,7 +43,7 @@ void perf_deque_push_front(void) void perf_deque_pop_front(void) { - for (size_t i = 0; i < g_test_obj.capacity; i++) + for (size_t i = 0; i < g_test_obj.run_count; i++) { deque->pop_front(deque, &g_test_obj.obj); } @@ -59,6 +59,9 @@ void perf_deque(size_t id) RUN_PERF(id, perf_deque_new()); RUN_PERF(id, perf_deque_push_back() ); RUN_PERF(id, perf_deque_pop_back() ); + RUN_PERF(id, perf_deque_free() ); + + RUN_PERF(id, perf_deque_new()); RUN_PERF(id, perf_deque_push_front() ); RUN_PERF(id, perf_deque_pop_front() ); RUN_PERF(id, perf_deque_free() ); diff --git a/perf/perf_log.c b/perf/perf_log.c index d93e523..cccb69d 100644 --- a/perf/perf_log.c +++ b/perf/perf_log.c @@ -123,7 +123,7 @@ static void perf_log_print_header(void) printf(PERF_FORMAT_FUNC, " function "); for(size_t i = 0; i < count; ++i) { - printf(" T%-2d(ms)", i); + printf(" T%-2d(us)", i); } printf("\n"); diff --git a/perf/perf_queue.c b/perf/perf_queue.c index 8364d6e..62ad4db 100644 --- a/perf/perf_queue.c +++ b/perf/perf_queue.c @@ -19,7 +19,7 @@ void perf_queue_new(void) void perf_queue_push(void) { - for (size_t i = 0; i < g_test_obj.capacity; i++) + for (size_t i = 0; i < g_test_obj.run_count; i++) { queue->push(queue, &g_test_obj.obj); } @@ -27,7 +27,7 @@ void perf_queue_push(void) void perf_queue_pop(void) { - for (size_t i = 0; i < g_test_obj.capacity; i++) + for (size_t i = 0; i < g_test_obj.run_count; i++) { queue->pop(queue, &g_test_obj.obj); } diff --git a/perf/perf_ringbuf.c b/perf/perf_ringbuf.c new file mode 100644 index 0000000..0cac263 --- /dev/null +++ b/perf/perf_ringbuf.c @@ -0,0 +1,76 @@ +/** + * @file perf_ringbuf.c + * @author wenjf (orig5826@163.com) + * @brief + * @version 0.1 + * @date 2026-05-21 + * + * @copyright Copyright (c) 2026 + * + */ +#include "perf.h" + +static ringbuf_t ringbuf = NULL; + +void perf_ringbuf_new(void) +{ + ringbuf = ringbuf_new(g_test_obj.obj_size, g_test_obj.capacity); +} + +void perf_ringbuf_push_back(void) +{ + for (size_t i = 0; i < g_test_obj.run_count; i++) + { + ringbuf->push_back(ringbuf, &g_test_obj.obj); + } +} + +void perf_ringbuf_pop_back(void) +{ + for (size_t i = 0; i < g_test_obj.run_count; i++) + { + ringbuf->pop_back(ringbuf, &g_test_obj.obj); + } +} + +void perf_ringbuf_push_front(void) +{ + for (size_t i = 0; i < g_test_obj.run_count; i++) + { + ringbuf->push_front(ringbuf, &g_test_obj.obj); + } +} + +void perf_ringbuf_pop_front(void) +{ + for (size_t i = 0; i < g_test_obj.run_count; i++) + { + ringbuf->pop_front(ringbuf, &g_test_obj.obj); + } +} + +void perf_ringbuf_free(void) +{ + ringbuf_free(&ringbuf); +} + +void perf_ringbuf(size_t id) +{ + RUN_PERF(id, perf_ringbuf_new()); + RUN_PERF(id, perf_ringbuf_push_back() ); + RUN_PERF(id, perf_ringbuf_pop_back() ); + RUN_PERF(id, perf_ringbuf_free() ); + + RUN_PERF(id, perf_ringbuf_new()); + RUN_PERF(id, perf_ringbuf_push_front() ); + RUN_PERF(id, perf_ringbuf_pop_front() ); + RUN_PERF(id, perf_ringbuf_free() ); +} + +void perf_test_ringbuf(void) +{ + for(size_t i = 0; i < PERF_TEST_TIEMS; i++) + { + PERF_ADD(i, perf_ringbuf); + } +} diff --git a/perf/perf_segarray.c b/perf/perf_segarray.c new file mode 100644 index 0000000..ffa3ca9 --- /dev/null +++ b/perf/perf_segarray.c @@ -0,0 +1,76 @@ +/** + * @file perf_segarray.c + * @author wenjf (orig5826@163.com) + * @brief + * @version 0.1 + * @date 2026-05-21 + * + * @copyright Copyright (c) 2026 + * + */ +#include "perf.h" + +static segarray_t segarray = NULL; + +void perf_segarray_new(void) +{ + segarray = segarray_new(g_test_obj.obj_size, g_test_obj.capacity); +} + +void perf_segarray_push_back(void) +{ + for (size_t i = 0; i < g_test_obj.run_count; i++) + { + segarray->push_back(segarray, &g_test_obj.obj); + } +} + +void perf_segarray_pop_back(void) +{ + for (size_t i = 0; i < g_test_obj.run_count; i++) + { + segarray->pop_back(segarray, &g_test_obj.obj); + } +} + +void perf_segarray_push_front(void) +{ + for (size_t i = 0; i < g_test_obj.run_count; i++) + { + segarray->push_front(segarray, &g_test_obj.obj); + } +} + +void perf_segarray_pop_front(void) +{ + for (size_t i = 0; i < g_test_obj.run_count; i++) + { + segarray->pop_front(segarray, &g_test_obj.obj); + } +} + +void perf_segarray_free(void) +{ + segarray_free(&segarray); +} + +void perf_segarray(size_t id) +{ + RUN_PERF(id, perf_segarray_new()); + RUN_PERF(id, perf_segarray_push_back() ); + RUN_PERF(id, perf_segarray_pop_back() ); + RUN_PERF(id, perf_segarray_free() ); + + RUN_PERF(id, perf_segarray_new()); + RUN_PERF(id, perf_segarray_push_front() ); + RUN_PERF(id, perf_segarray_pop_front() ); + RUN_PERF(id, perf_segarray_free() ); +} + +void perf_test_segarray(void) +{ + for(size_t i = 0; i < PERF_TEST_TIEMS; i++) + { + PERF_ADD(i, perf_segarray); + } +} diff --git a/perf/perf_stack.c b/perf/perf_stack.c index 680f391..7d3ee34 100644 --- a/perf/perf_stack.c +++ b/perf/perf_stack.c @@ -19,7 +19,7 @@ void perf_stack_new(void) void perf_stack_push(void) { - for (size_t i = 0; i < g_test_obj.capacity; i++) + for (size_t i = 0; i < g_test_obj.run_count; i++) { stack->push(stack, &g_test_obj.obj); } @@ -27,7 +27,7 @@ void perf_stack_push(void) void perf_stack_pop(void) { - for (size_t i = 0; i < g_test_obj.capacity; i++) + for (size_t i = 0; i < g_test_obj.run_count; i++) { stack->pop(stack, &g_test_obj.obj); } diff --git a/run.bat b/run.bat index 981fbeb..42cc3f8 100644 --- a/run.bat +++ b/run.bat @@ -1,2 +1,2 @@ -start /b /wait build/release/bin/demo.exe -@REM start /b /wait build/release/bin/perf.exe +@REM start /b /wait build/release/bin/demo.exe +start /b /wait build/release/bin/perf.exe diff --git a/src/heap.c b/src/heap.c index 1669a23..8ad9191 100644 --- a/src/heap.c +++ b/src/heap.c @@ -60,8 +60,6 @@ static void heap_fixed_up(struct _heap* self, size_t i) } obj_swap(base, i, p, obj_size); i = p; - - self->print(self); } } else /* if(self->_type == HEAP_MIN) */ @@ -78,8 +76,6 @@ static void heap_fixed_up(struct _heap* self, size_t i) } obj_swap(base, i, p, obj_size); i = p; - - self->print(self); } } } @@ -170,7 +166,7 @@ static bool heap_pop(struct _heap* self, void* obj) return true; } -static size_t heap_reserve(struct _heap* self, size_t capacity) +static bool heap_reserve(struct _heap* self, size_t capacity) { unicstl_assert(self != NULL); unicstl_assert(self->_darray != NULL);