测试用例编写

This commit is contained in:
2026-01-10 18:31:26 +08:00
parent 1adb24482b
commit 1a7c1c172c
13 changed files with 98 additions and 19 deletions

3
.gitignore vendored
View File

@@ -1,9 +1,6 @@
NtyCo/
.vscode/
img/
*.db
*.copy
proactor copy.c
ntyco copy.c
reactor copy.c

View File

@@ -10,18 +10,40 @@ save() -> 全保存数据集。
1. 会出现大量的内存碎片,实现一个内存池,管理内存数据。
2. 对比有内存池和没有内存池的性能差异,以及开源内存池 jemalloc 的性能差别。
`sudo apt-get install -y libjemalloc-dev`
3. 性能测:
1. qps 有没有内存池。
![alt text](img/无内存池.png)
2.虚拟内存的占用情况 htop。插入百万条数据集(KV*100wset 200w del 100w delete 200w set 100w)。
![alt text](img/未运行状态.png)
![alt text](img/200w插入100w删除.png)
![alt text](img/100w插入200w删除.png)
![alt text](img/无内存池200w条插入100w删除.png)
无内存池: --> time_used=1488789 ms, ops=6000000, qps=4030
![alt text](img/mpalloc200w插入100w删除.png)
自实现内存池: --> time_used=1439444 ms, ops=6000000, qps=4168
测试:
虚拟内存的占用情况 htop。插入百万条数据集(KV*100wset 200w del 100w delete 200w set 100w)。
##### 单条插入
未运行状态 VIRT 24.8M
![alt text](img/未运行状态.png)
无内存池: --> time_used=1488789 ms, ops=6000000, qps=4030\
VIRT 105M
![alt text](img/无内存池200w插入100w删除.png)
自实现内存池: --> time_used=1439444 ms, ops=6000000, qps=4168\
VIRT 135M
![alt text](img/mpalloc200w插入100w删除.png)
![alt text](img/jemalloc2000w插入100w删除.png)
jemalloc: time_used=1502797 ms, ops=6000000, qps=3992\
VIRT 99M
##### 批处理
一次执行100条。
无内存池:--> time_used=142913 ms, ops=6000000, qps=41983\
VIRT 99M
自实现内存池: --> time_used=122754 ms, ops=6000000, qps=48878\
VIRT 135M
jemalloc--> time_used=122206 ms, ops=6000000, qps=49097\
VIRT 99M
性能分析:
1. key :

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
img/批处理jemalloc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
img/未运行状态.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -26,7 +26,6 @@ void kvs_free(void *ptr) {
#if MEMORY_SELECT_MALLOC == MEMORY_USE_MYMALLOC
mp_pool_t global_mempool = {0};
#endif
// >= x 的第一个2^n
uint32_t mp_ceil_pow2_u32(uint32_t x) {
@@ -162,3 +161,4 @@ void mp_free(void* ptr){
node->next = p->buckets[cid].free_list;
p->buckets[cid].free_list = node;
}
#endif

View File

@@ -5,7 +5,7 @@
#define MEMORY_USE_MYMALLOC 1
#define MEMORY_USE_JEMALLOC 2
#define MEMORY_SELECT_MALLOC MEMORY_USE_MYMALLOC
#define MEMORY_SELECT_MALLOC MEMORY_USE_JEMALLOC
#include <stddef.h>
#include <stdint.h>

View File

@@ -16,7 +16,7 @@
#define CMD_SIZE (1024)
#define BATCH_SIZE (65536)
#define KVS_BATCH_MAX 64
#define KVS_BATCH_MAX 128
#define TIME_SUB_MS(tv1, tv2) ((tv1.tv_sec - tv2.tv_sec) * 1000 + (tv1.tv_usec - tv2.tv_usec) / 1000)
// #define PRESP print_response

View File

@@ -163,7 +163,7 @@ void do_batch_test(int fd, int op, const char *key, const char *value){
char bkey[15]={0}, bval[15]={0};
// 组 batch最多 64 条)
for(int i = 0;i < 48; ++ i){
for(int i = 0;i < 100; ++ i){
if(value == NULL){
int klen = sprintf(bkey, "%s%d", key, i);
kvs_batch_add(&batch, op, bkey, klen, NULL, 0);
@@ -190,6 +190,64 @@ void do_batch_test(int fd, int op, const char *key, const char *value){
}
}
void batch_qps(int connfd) {
const int N = 1000000;
const int B = 100; // do_batch_test() 里写死 50
const char *valA = "va";
const char *valB = "vb";
const char *valC = "vc";
struct timeval tv_begin, tv_end;
gettimeofday(&tv_begin, NULL);
// ---------------- Phase 1: ADD 两条 DEL 一条 (100w) ----------------
// 每轮ADD/SET A_i, ADD/SET B_i, DEL A_i
// 用 batch每批处理 idx..idx+49
for (int base = 0; base < N; base += B) {
// prefix 必须短,避免 do_batch_test 里 bkey[15] 溢出
// do_batch_test 会生成: prefix + i (0..49)
// 我们把 base 编进 prefix保证全局 key 唯一
char preA[16], preB[16];
// 例A123450_0..A123450_49base=123450
// 注意:这里 prefix 长度要尽量 <= 10 左右
snprintf(preA, sizeof(preA), "A%d_", base/100);
snprintf(preB, sizeof(preB), "B%d_", base/100);
do_batch_test(connfd, KVS_CMD_RSET, preA, valA); // 50次 RSET A
do_batch_test(connfd, KVS_CMD_RSET, preB, valB); // 50次 RSET B
do_batch_test(connfd, KVS_CMD_RDEL, preA, NULL); // 50次 RDEL A
if (base % 10000 == 0) printf("P1 base:%d\n", base);
}
printf("phase 1 end\n");
// ---------------- Phase 2: ADD 一条 DEL 两条 (100w) ----------------
// 每轮ADD/SET C_i, DEL B_i, DEL C_i
for (int base = 0; base < N; base += B) {
char preB[16], preC[16];
snprintf(preB, sizeof(preB), "B%d_", base/100);
snprintf(preC, sizeof(preC), "C%d_", base/100);
do_batch_test(connfd, KVS_CMD_RSET, preC, valC); // 50次 RSET C
do_batch_test(connfd, KVS_CMD_RDEL, preB, NULL); // 50次 RDEL B
do_batch_test(connfd, KVS_CMD_RDEL, preC, NULL); // 50次 RDEL C
if (base % 10000 == 0) printf("P2 base:%d\n", base);
}
printf("phase 2 end\n");
gettimeofday(&tv_end, NULL);
int time_used = TIME_SUB_MS(tv_end, tv_begin);
// 真实总 ops 还是 6*N (每轮 6 个操作)
long long ops = (long long)N * 6;
long long qps = (time_used > 0) ? (ops * 1000 / time_used) : 0;
printf("BATCH(do_batch_test) ADD2-DEL1 then ADD1-DEL2 (N=%d) --> time_used=%d ms, ops=%lld, qps=%lld\n",
N, time_used, ops, qps);
}
void save(int connfd){
testcase(connfd, KVS_CMD_SAVE, NULL, 0, NULL, 0, KVS_STATUS_OK, NULL, 0, "SAVE");
}
@@ -303,6 +361,8 @@ int main(int argc, char *argv[]) {
do_batch_test(connfd, KVS_CMD_HEXIST, "hash_set", NULL);
}else if(mode == -1){
save(connfd);
}else if(mode == 4){
batch_qps(connfd);
}
return 0;
}