|
| 1 | +# F-Stack 13.0 baseline vs 15.0 runtime-fix-done — CVM 同时序压测报告 |
| 2 | + |
| 3 | +> **报告时间**:2026-06-03 15:08-15:14(UTC+8) |
| 4 | +> **测试主机**:腾讯云 CVM(NUMA 1 节点,dpdk virtio_net 驱动 PCI 00:09.0) |
| 5 | +> **F-Stack server**:9.134.214.176(本机) |
| 6 | +> **wrk client**:`f-stack-client` 别名(9.134.211.87:36000,root@VM-211-87-tencentos) |
| 7 | +> **关联文档**:`runtime-fix-execution-log.md` §12.10(双份落档) |
| 8 | +
|
| 9 | +--- |
| 10 | + |
| 11 | +## 1. 测试目标 |
| 12 | + |
| 13 | +回答两个遗留问题: |
| 14 | + |
| 15 | +1. **§12.6 既有 15.0 单边数据(226k/231k req/s)是否已被同硬件 13.0 老基线公平对照?** —— 此前未做,无 13.0 老基线作 sanity reference。 |
| 16 | +2. **runtime-fix 6 个 commit(5 P0 修复 + 1 防御性)是否引入隐性性能 regression?** —— 此前缺同时序 A/B。 |
| 17 | + |
| 18 | +## 2. 测试方法 & 公平性论证 |
| 19 | + |
| 20 | +### 2.1 同时序 A/B |
| 21 | + |
| 22 | +13.0 baseline 与 15.0 runtime-fix-done 在**同一台 CVM 同分钟(15:08-15:13)连续切换**,消除跨日网络/温度/CPU 频率漂移影响。两版 helloworld 各跑同三场景,全程 ≈ 6 分钟。 |
| 23 | + |
| 24 | +### 2.2 公平变量 |
| 25 | + |
| 26 | +| 变量 | 13.0 baseline | 15.0 runtime-fix-done | 一致性 | |
| 27 | +|---|---|---|---| |
| 28 | +| dpdk 版本 | 23.11.5(系统已装) | 23.11.5(同份) | ✅ 完全一致(pkg-config --modversion 验证) | |
| 29 | +| dpdk lib install 路径 | `/usr/local/lib64/` | 同 | ✅ 同份 .so 文件 | |
| 30 | +| config.ini | `lcore_mask=10` 单 lcore CPU#4 | 同 | ✅ `diff` exit 0 | |
| 31 | +| Port 配置 | port0 9.134.214.176/21, idle_sleep=20, tso=0 | 同 | ✅ 同 config.ini | |
| 32 | +| example/Makefile | `-L${FF_PATH}/lib -Wl,--whole-archive,-lfstack` | 同 | ✅ `diff` exit 0 | |
| 33 | +| F-Stack 监听端口 | 80 (htons in main.c) | 同 | ✅ 同源 main.c | |
| 34 | +| wrk client | f-stack-client `/tmp/wrk/wrk` 同实例 | 同 | ✅ 同 ssh 会话连续触发 | |
| 35 | +| wrk 参数 | T1/T2/T3 同 §12.6 | 同 | ✅ 沿用历史参数 | |
| 36 | +| 编译类型 | `-O0 -g -gdwarf-2` | 同 | ✅ Makefile 一致 | |
| 37 | + |
| 38 | +### 2.3 唯一变量(Δ source) |
| 39 | + |
| 40 | +唯一差异 = **F-Stack lib + freebsd kernel 源码差**(13.0 vs 15.0 vendor + 6 runtime-fix patch)。 |
| 41 | + |
| 42 | +## 3. 编译过程 |
| 43 | + |
| 44 | +### 3.1 13.0 baseline 编译 |
| 45 | + |
| 46 | +```text |
| 47 | +FF_PATH=/data/workspace/f-stack-13.0-baseline |
| 48 | +PKG_CONFIG_PATH=/usr/lib64/pkgconfig:/usr/local/lib64/pkgconfig:/usr/lib/pkgconfig |
| 49 | +cd $FF_PATH/lib && make -j$(nproc) # 10s, 191 .o, libfstack.a 4.9MB |
| 50 | +cd $FF_PATH/example && make -j$(nproc) # 2s, helloworld 27.9MB |
| 51 | +``` |
| 52 | + |
| 53 | +### 3.2 编译事件:`ff_api.symlist` 误判 |
| 54 | + |
| 55 | +**首次 `make -j$(nproc)` 失败**: |
| 56 | + |
| 57 | +```text |
| 58 | +make: *** No rule to make target 'ff_api.symlist', needed by 'libfstack.a'. Stop. |
| 59 | +``` |
| 60 | + |
| 61 | +**根因**:preflight 阶段(Step 1)我用 `find -name '*.symlist'` 收集"产物"传给 `rm_tmp_file.sh`,但 `ff_api.symlist`(1148 字节,81 行符号导出列表)实际是**手工维护源文件**(lib/Makefile L673 把它列为 libfstack.a 前置依赖)。 |
| 62 | + |
| 63 | +**恢复**:rm_tmp_file.sh 是 mv→trash 设计(非真删),从 `/data/workspace/.trash/20260603-065813-1727226/data/workspace/f-stack-13.0-baseline/lib/ff_api.symlist` 用 `cp -p` 复原(sha256 `b70dfbca…3f5c523`,与主树和 runtime-fix-done 树完全一致),随后重编成功。 |
| 64 | + |
| 65 | +**经验教训**:`*.symlist` 不能盲目当产物清理;后续清理脚本需 whitelist 明确扩展名(仅 `.o` + `libfstack.a`)。 |
| 66 | + |
| 67 | +### 3.3 编译产物双备份 |
| 68 | + |
| 69 | +| 用途 | 路径 | sha256 | 大小 | |
| 70 | +|---|---|---|---| |
| 71 | +| 13.0 baseline binary | `/data/workspace/f-stack-13.0-baseline/example/helloworld_13baseline` | `5b6df6d3312392ff0f7a193d661543b7329883815e587774eb1f71929ef53ad5` | 27,934,872 B | |
| 72 | +| 15.0 runtime-fix-done binary | `/data/workspace/f-stack/example/helloworld_15rfix` | `4e3f3c75bc0145864272a5fb470bb90615d9818df28f3faa0b7fc014fb53c3b9` | 28,263,952 B | |
| 73 | +| 13.0 libfstack.a | `/data/workspace/f-stack-13.0-baseline/lib/libfstack.a` | `429507d9922a0ff30a10afc424b41a45197fb86f0ebf35f4dda5b4034375051d` | 4,897,214 B | |
| 74 | + |
| 75 | +后续场景切换:`cp helloworld_<ver> ./example/helloworld && ./start.sh`,无需重编。 |
| 76 | + |
| 77 | +## 4. 测试场景 & 原始数据 |
| 78 | + |
| 79 | +### 4.1 测试矩阵 |
| 80 | + |
| 81 | +沿用 `runtime-fix-execution-log.md` §12.6 三场景: |
| 82 | + |
| 83 | +| 场景 | wrk 参数 | 时长 | 用途 | |
| 84 | +|---|---|---|---| |
| 85 | +| T1 warmup | `-t2 -c10 --latency` | 5s | 链路探活 + 缓存预热 | |
| 86 | +| T2 baseline | `-t4 -c100 --latency` | 30s | 中负载吞吐 | |
| 87 | +| T3 high-conc | `-t8 -c500 --latency` | 30s | 高并发长尾 | |
| 88 | + |
| 89 | +### 4.2 13.0 baseline 原始数据 |
| 90 | + |
| 91 | +| 场景 | Requests/sec | Avg Lat | p50 | p75 | p90 | p99 | Total req | Transfer/s | |
| 92 | +|---|---:|---:|---:|---:|---:|---:|---:|---:| |
| 93 | +| T1 | **24,413.98** | 405.78us | 392us | 457us | 501us | **600us** | 124,506 / 5.10s | 15.11 MB/s | |
| 94 | +| T2 | **220,690.99** | 520.39us | 536us | 591us | 643us | **811us** | 6,622,780 / 30.01s | 136.59 MB/s | |
| 95 | +| T3 | **239,554.56** | 2.14ms | 2.19ms | 2.24ms | 2.34ms | **4.21ms** | 7,193,126 / 30.03s | 148.27 MB/s | |
| 96 | + |
| 97 | +原始 wrk 输出:`/tmp/13baseline-bench/T{1,2,3}.txt` |
| 98 | + |
| 99 | +### 4.3 15.0 runtime-fix-done 原始数据 |
| 100 | + |
| 101 | +| 场景 | Requests/sec | Avg Lat | p50 | p75 | p90 | p99 | Total req | Transfer/s | |
| 102 | +|---|---:|---:|---:|---:|---:|---:|---:|---:| |
| 103 | +| T1 | **23,757.29** | 425.30us | 399us | 464us | 513us | **838us** | 121,146 / 5.10s | 14.70 MB/s | |
| 104 | +| T2 | **203,932.53** | 530.22us | 530us | 585us | 642us | **827us** | 6,120,893 / 30.01s | 126.22 MB/s | |
| 105 | +| T3 | **217,099.82** | 2.27ms | 2.24ms | 2.33ms | 2.56ms | **5.38ms** | 6,525,758 / 30.06s | 134.37 MB/s | |
| 106 | + |
| 107 | +原始 wrk 输出:`/tmp/15rfix-bench/T{1,2,3}.txt` |
| 108 | + |
| 109 | +## 5. 同时序对比与 §12.6 历史交叉对比 |
| 110 | + |
| 111 | +### 5.1 同时序 A/B(13.0 vs 15.0,同硬件同分钟) |
| 112 | + |
| 113 | +| 场景 | 13.0 req/s | 15.0 req/s | Δ req/s | 13.0 p99 | 15.0 p99 | Δ p99 | |
| 114 | +|---|---:|---:|---:|---:|---:|---:| |
| 115 | +| T1 t2c10 5s | 24,414 | 23,757 | **−2.69%** | 600us | 838us | **+39.7%** | |
| 116 | +| T2 t4c100 30s | **220,691** | **203,933** | **−7.59%** | 811us | 827us | +2.0% | |
| 117 | +| T3 t8c500 30s | **239,555** | **217,100** | **−9.37%** | 4.21ms | 5.38ms | **+27.8%** | |
| 118 | + |
| 119 | +### 5.2 §12.6 历史 15.0 (06-02) vs 本次同时序 15.0 (06-03) |
| 120 | + |
| 121 | +| 场景 | §12.6 历史 (06-02) | 本次 15.0 (06-03) | 偏差 | |
| 122 | +|---|---:|---:|---:| |
| 123 | +| T2 t4c100 30s | 226,065 | 203,933 | **−9.79%** | |
| 124 | +| T3 t8c500 30s | 231,106 | 217,100 | **−6.06%** | |
| 125 | + |
| 126 | +**解读**:跨日 6-10% 偏差源于网络/CPU 频率抖动;§12.6 数据**不能**作为干净基线对照,**本次同时序对比才是公允 A/B**。 |
| 127 | + |
| 128 | +## 6. 关键发现 |
| 129 | + |
| 130 | +### 6.1 性能 regression 实证 |
| 131 | + |
| 132 | +**runtime-fix-done (15.0) 相比 13.0 baseline 在同硬件同配置下:** |
| 133 | + |
| 134 | +- T2 中负载 **−7.59%** (220,691 → 203,933 req/s) |
| 135 | +- T3 高并发 **−9.37%** (239,555 → 217,100 req/s),p99 **+27.8%** (4.21ms → 5.38ms) |
| 136 | +- T1 轻负载 **−2.69%**,但 p99 长尾 **+39.7%** (600us → 838us) |
| 137 | + |
| 138 | +### 6.2 性能特征推断 |
| 139 | + |
| 140 | +| 观察 | 推断 | |
| 141 | +|---|---| |
| 142 | +| T1 轻负载差距小(仅吞吐 −2.7%)但 p99 长尾恶化 +40% | 单 connection 路径无新瓶颈,但偶发长尾事件(GC/锁/中断)增加 | |
| 143 | +| T2/T3 中高并发吞吐与 p99 同步劣化,且高并发劣化更大 | 锁竞争/per-CPU 数据结构改动相关性高 | |
| 144 | +| Avg latency 在三场景都增加 ~5% | base 路径开销系统性提升(可能 epoch/atomic 改动) | |
| 145 | + |
| 146 | +### 6.3 怀疑根因(需 perf 进一步证实) |
| 147 | + |
| 148 | +5 个 runtime-fix 修复 + 1 防御性 panic stub 中: |
| 149 | + |
| 150 | +1. **P3 (kern_descrip 边界下移 + `badfileops` 恢复)** —— 涉及 `kern_accept` 错误路径,**accept(2) 是高并发 fastpath**,回退 stub 后 file descriptor 创建/销毁可能引入额外原子操作 |
| 151 | +2. **P1-2 (atomic.h `__storeload_barrier` `_KERNEL` 路径修复)** —— 修复了 SIGSEGV 但同时**启用了真正的 storeload 屏障**,在 SMP 环境每次 store-load 都有内存屏障开销,对 hot path 影响大 |
| 152 | +3. **P2 (Phase 2 route_rtentry / 11 stub)** —— 启用了真实路由查找,每包 IP 处理多一次 routing table lookup |
| 153 | +4. **Phase 1+2+3 累计 fixes** 把"短路 stub"逐步还原为"真实 FreeBSD 路径",性能 trade-off 是预期的(**正确性换性能**) |
| 154 | + |
| 155 | +## 7. 后续行动建议(不在本次范围) |
| 156 | + |
| 157 | +| 选项 | 工作量 | 预期收益 | |
| 158 | +|---|---|---| |
| 159 | +| **A. perf flamegraph 双版叠图** | 0.5d | 直接定位 hot path 分歧(首选) | |
| 160 | +| **B. lockstat / mutex 统计** | 1d | 量化锁竞争(若 perf 显示锁热) | |
| 161 | +| **C. 二分回退某 commit 单测** | 2d | 隔离 9% gap 来源到具体修复 | |
| 162 | +| **D. dpdk EAL 参数对齐复测** | 0.5d | 排除 mempool/RING/burst size 干扰 | |
| 163 | +| **E. 接受 9% gap,进入 M5 验收** | 0d | 客观 trade-off:正确性优先(5 个 P0 SIGSEGV 修复价值远大于 9% 吞吐) | |
| 164 | + |
| 165 | +## 8. 系统终态 |
| 166 | + |
| 167 | +| 项 | 状态 | |
| 168 | +|---|---| |
| 169 | +| 13.0 baseline helloworld | 已 kill (PID 1735251),hugepages 23 rtemap 已清入 trash `20260603-071317-1737799` | |
| 170 | +| 15.0 runtime-fix-done helloworld | **仍后台在跑**(PID 1738072, lcore=4, hugepages 23/4096, port0 9.134.214.176:80) | |
| 171 | +| 当前 helloworld log | `/tmp/15rfix-bench/hello.log` | |
| 172 | +| 双 binary 备份 | 见 §3.3,sha256 已记录 | |
| 173 | +| 13.0 baseline 树状态 | `/data/workspace/f-stack-13.0-baseline/lib/` 完整编译,可随时切换 | |
| 174 | +| 15.0 主树状态 | `/data/workspace/f-stack/` 不变(runtime-fix-done 状态 + 已 push) | |
| 175 | + |
| 176 | +## 9. 强制规约遵守证据 |
| 177 | + |
| 178 | +| 规约 | 证据 | |
| 179 | +|---|---| |
| 180 | +| DP-10 / `rm_tmp_file.sh` | 全程零直接 rm;3 次脚本调用:①rtemap×23(pre-launch)②lib 产物×195(pre-build)③rtemap×23(pre-15.0-launch) | |
| 181 | +| `kill_process.sh` | 全程零直接 kill;2 次脚本调用:①13.0 helloworld 收尾(PID 1071620 in Step 1)②13.0 baseline 跑完后切换 (PID 1735251) | |
| 182 | +| `chmod_modify.sh` | 本次未涉及权限修改 | |
| 183 | +| commit message 英文 | 见伴随 commit `docs(bench): add 13.0-baseline vs 15.0-runtime-fix-done CVM comparison` | |
| 184 | + |
| 185 | +## 10. 参考 |
| 186 | + |
| 187 | +- `runtime-fix-execution-log.md` §12.6 (历史 15.0 单边数据起源) |
| 188 | +- `runtime-fix-execution-log.md` §12.10 (同摘要双份落档) |
| 189 | +- spec 06-test-and-acceptance-spec.md §5 (性能基线 NFR-1 整体框架) |
| 190 | +- preflight log: `/tmp/13baseline-bench/preflight.log` |
| 191 | +- 编译 log: `/tmp/13baseline-bench/lib_make.log` + `/tmp/13baseline-bench/example_make.log` |
0 commit comments