|
1 | 1 | # 21 · M2 测试执行报告(ZC-RECV) |
2 | 2 |
|
3 | | -> 执行:2026-06-11。双机:server=本机(VM-213-67,data-plane DPDK NIC 9.134.214.176 / MAC 20:90:6f:7d:5d:08,云 metadata 实测确认);client=f-stack-client(VM-211-87,9.134.211.87)。 |
| 3 | +> 执行:2026-06-11。双机:server=本机(VM-213-67,data-plane DPDK NIC 9.134.214.176 / MAC 20:90:6f:7d:5d:08,云 metadata 实测确认);client=f-stack-client(VM-211-87,9.134.211.87,wrk 4.2.0 @ /tmp/wrk/wrk)。 |
4 | 4 | > 铁律:仅记录实际执行结果,不臆造数据。 |
5 | 5 |
|
6 | | -## 1. 构建 / 启动验证(PASS) |
7 | | -| 项 | 命令 | 结果 | |
8 | | -|---|---|---| |
9 | | -| lib(FF_ZC_SEND=1 FF_ZC_RECV=1)| `make -C lib` | ✅ rc=0,-Werror 零错误 | |
10 | | -| 符号导出 | nm libfstack.a | ✅ `T ff_zc_recv / ff_zc_mbuf_segment / ff_zc_recv_free`(已补 ff_api.symlist)| |
11 | | -| server B(ZC-recv,-DFSTACK_ZC_SEND -DFSTACK_ZC_RECV)| cc main_zc.c | ✅ helloworld_zc_recv(29036792 B)| |
12 | | -| server A(baseline,仅 -DFSTACK_ZC_SEND)| cc main_zc.c | ✅ helloworld_zc_base(29036576 B,略小,确认 ZC-recv 代码已链接进 B)| |
13 | | -| server B 启动 | `./helloworld_zc_recv --conf config.ini --proc-type=primary` | ✅ DPDK EAL init OK,`Successed to register dpdk interface`,MAC 20:90:6f:7d:5d:08 | |
14 | | - |
15 | | -## 2. 功能集成(curl)—— 被环境阻断,已证明与 ZC-recv 代码无关 |
16 | | -### 2.1 现象 |
17 | | -client `curl http://9.134.214.176/` 连续多次均 `http=000`(连接建立失败,time≈0.001s 即返回),server CPU 始终 ~9.5%(idle_sleep 下基本空闲)→ **SYN 包未到达 f-stack**。 |
18 | | - |
19 | | -### 2.2 网络诊断(实测) |
20 | | -- 云 metadata:`MAC 20:90:6f:7d:5d:08 ↔ IP 9.134.214.176`(DPDK NIC,config.ini addr 正确);`MAC 52:54:00:9e:8b:6f ↔ 9.134.213.67`(控制面 eth1)。 |
21 | | -- client 与 data-plane 同 /21 子网(9.134.208.0/21),`ip route get 9.134.214.176 → dev eth1`(直连)。 |
22 | | -- client ARP:`9.134.214.176 → fe:ee:2e:9c:ed:94`(VPC 网关/SDN MAC,非 f-stack 也非控制面);刷新 ARP 后仍解析为该 MAC。 |
23 | | -- **结论**:VPC SDN 未把发往 9.134.214.176 的报文投递到该 ENI 对应的 DPDK NIC(f-stack 收不到任何包)。 |
| 6 | +## 1. 根因与修复(关键) |
| 7 | +首轮 curl 全部 http=000,曾误判为"环境问题"。经用户纠正(普通 helloworld 在 client 测试 http=200 正常)后实际调试,定位**真实根因**: |
24 | 8 |
|
25 | | -### 2.3 差分判定(关键,证明非本次代码问题) |
26 | | -| Server | 接收路径 | curl 结果 | server CPU | |
27 | | -|---|---|---|---| |
28 | | -| B(ZC-recv,本次新代码)| ff_zc_recv | http=000 ×5 | ~9.4% 空闲 | |
29 | | -| **A(baseline,纯 ff_read,历史可用路径,无任何 ZC-recv 代码)** | ff_read | **http=000 ×3(完全一致)** | ~9.5% 空闲 | |
| 9 | +- **增量编译陷阱**:先做了无 flag 的 baseline build(所有 .o 不含 FSTACK_ZC_SEND),随后 `FF_ZC_SEND=1 make` 因 `uipc_mbuf.c` 未改动、其 .o(06-09 15:48)比 .c 新而**被 make 跳过未重编译** → `m_uiotombuf` 的 FSTACK_ZC_SEND 内核 hook **缺失**(objdump 验证 magic `0xf8ac2c00` 不在 uipc_mbuf.o)。 |
| 10 | +- 后果:`ff_zc_send`(应答路径,A/B 两版都用)设了 magic 但内核 hook 不识别 → 把 mbuf 链指针当 char buffer → 应答崩坏,连接不可用 → http=000。 |
| 11 | +- **这也解释了为何 A(baseline) 与 B(ZC-recv) 都失败**(两者应答都走 ff_zc_send)。 |
| 12 | +- **修复**:删除 stale 的 `uipc_mbuf.o` / `sys_generic.o`(经 rm_tmp_file.sh),带 `FF_ZC_SEND=1 FF_ZC_RECV=1` 重编译;objdump 验证 uipc_mbuf.o 现含 `movabs $0xf8ac2c00f8ac2c00`。重链 libfstack.a + 重建 server。 |
| 13 | +- **构建规约(记入)**:变更 FF_ZC_* 等编译开关后**必须 `make clean` 或删除受影响 .o 后重编译**,不能依赖增量编译(make 基于时间戳,不感知 CFLAGS 变化)。 |
30 | 14 |
|
31 | | -→ **baseline 与 ZC-recv 表现完全一致、包都未到达 f-stack** ⇒ 阻断点是**数据面 VPC/ENI 投递(环境)**,**与 ZC-recv 实现无关**。本次 M0+M1 代码的编译、符号导出、server 启动、DPDK 注册均正常。 |
| 15 | +## 2. 功能验证(PASS,修复后) |
| 16 | +| 项 | 结果 | |
| 17 | +|---|---| |
| 18 | +| lib(clean+FF_ZC_SEND=1 FF_ZC_RECV=1)| ✅ -Werror 零错误;uipc_mbuf.o 含 ZC-send hook | |
| 19 | +| 符号导出 | ✅ ff_zc_recv / ff_zc_mbuf_segment / ff_zc_recv_free | |
| 20 | +| server B(ZC-recv)启动 | ✅ DPDK 注册 OK | |
| 21 | +| **client curl ×5** | ✅ **http=200 size=438**(ff_zc_recv→segment→free 全链路 + ff_zc_send 应答均正常)| |
32 | 22 |
|
33 | | -## 3. 性能基线对比 —— 因数据面阻断无法采集真实数值 |
34 | | -- 单核(lcore_mask=10 → lcore 4)A/B 压测 harness 已就绪(见 §5),但因 §2 数据面阻断,**本轮无法采集真实 req/s**。**不臆造数据**。 |
35 | | -- **历史极限参考**(docs/freebsd_13_to_15 13.0-baseline-cvm-bench-report,同机同 config.ini 单核 lcore4,helloworld kqueue): |
36 | | - - Smoke curl:HTTP 200,RTT 1.25 ms |
37 | | - - T2(-t4 -c100 30s):13.0 **220,691 req/s** / 15.0 203,933 req/s |
38 | | - - T3(-t8 -c500 30s):13.0 **239,555 req/s** / 15.0 217,100 req/s,p99 4.21→5.38 ms |
39 | | -- ZC-recv 预期:消除 soreceive→uiomove 拷贝,大包收取场景 CPU/吞吐应有收益(待数据面恢复后用 §5 harness 实测 A/B)。 |
| 23 | +## 3. 单核性能基线 A/B(lcore_mask=10 → lcore4,wrk,按 freebsd-13-to-15 方法论 T1/T2/T3) |
| 24 | +A=baseline(ff_read 接收);B=ZC-recv(ff_zc_recv 接收);二者应答均 ff_zc_send,隔离接收路径差异。 |
40 | 25 |
|
41 | | -## 4. 数据面恢复建议(环境侧,非本代码) |
42 | | -VPC SDN 对 9.134.214.176→DPDK NIC 的转发绑定疑似失效(历史测试曾正常,环境漂移)。建议其一: |
43 | | -- 重新挂载/刷新该 ENI 的 IP-MAC 绑定(云控制台或 reboot); |
44 | | -- 或确认 SDN 反欺骗对 f-stack 主动 gratuitous ARP 的要求; |
45 | | -- 恢复后用 §5 harness 直接复测。 |
| 26 | +| 档位 | wrk 参数 | A baseline req/s | B ZC-recv req/s | Δ | |
| 27 | +|---|---|---|---|---| |
| 28 | +| T1 | -t2 -c10 -d5s | 22,363 | 22,115 | −1.1%(噪声)| |
| 29 | +| **T2** | -t4 -c100 -d30s | 31,056 / 32,136 / 30,066(avg **31.1k**)| 39,046(离群) / 32,219 / 31,987(avg **32.1k**,去离群)| **持平(≤+3%,噪声内)**| |
| 30 | +| T3 | -t8 -c500 -d30s | 28,615 | 28,317 | −1.0%(饱和)| |
46 | 31 |
|
47 | | -## 5. 就绪的复测 harness(数据面恢复后直接执行) |
48 | | -```bash |
49 | | -# 1) server B(ZC-recv,单核 lcore4) |
50 | | -cd /data/workspace/f-stack/example |
51 | | -nohup ./helloworld_zc_recv --conf /data/workspace/f-stack/config.ini --proc-type=primary >/tmp/zc_recv.log 2>&1 & disown |
| 32 | +> 注:B 首次 T2=39,046 经复测确认为 warmup/噪声离群值;3 次复测后 A≈B。 |
52 | 33 |
|
53 | | -# 2) smoke(client) |
54 | | -ssh f-stack-client "curl -s -o /dev/null -w 'http=%{http_code} t=%{time_total}\n' http://9.134.214.176/" |
| 34 | +延迟(T2):A avg 3.71ms / B avg 4.12ms;T3:A 17.87ms / B 18.06ms —— 同量级。 |
| 35 | +server 单核 CPU(T2):72–84%,**未饱和** → 该负载瓶颈在 client/网络,非 server 接收拷贝。 |
55 | 36 |
|
56 | | -# 3) 单核性能 T2/T3(client;如无 wrk 用 ab/curl 循环) |
57 | | -ssh f-stack-client "wrk -t4 -c100 -d30s --latency http://9.134.214.176/" |
58 | | -ssh f-stack-client "wrk -t8 -c500 -d30s --latency http://9.134.214.176/" |
| 37 | +## 4. 性能结论(诚实) |
| 38 | +- **此小包 echo 负载(256B 请求 / 438B 应答)下,ZC-recv 与 ff_read 吞吐/延迟持平(噪声内)**。 |
| 39 | +- 原因:小请求的 `soreceive→uiomove` 拷贝开销相对 TCP 处理 + syscall + 调度可忽略;且 f-stack 用 UIO_SYSSPACE,uiomove 本就是同地址空间 memcpy(已很廉价)。 |
| 40 | +- ZC-recv 的收益预期在 **大块数据收取 / 代理转发(收到即转发免拷贝)** 场景(spec 15/17 §适用场景),需用大 payload 工作负载(如大文件下载、大 body POST)专门测量;本轮 echo 负载无法体现。 |
| 41 | +- **历史极限参考**(同机同 config 单核 lcore4,helloworld kqueue,docs/freebsd_13_to_15 13.0-baseline):T2 220,691 / T3 239,555 req/s。本轮 main_zc(echo + 模拟 1 万次空循环 + ff_zc_send)req/s 远低于该 kqueue helloworld,因应用模型与负载不同(main_zc 每请求含人为 busy-loop 与 ZC 应答构造),不可直接横比。 |
59 | 42 |
|
60 | | -# 4) 停服务 + 清理(必须走脚本) |
61 | | -/data/workspace/kill_process.sh <pid> |
62 | | -ls /dev/hugepages/rtemap_* | xargs /data/workspace/rm_tmp_file.sh |
63 | | - |
64 | | -# 5) server A(baseline)重复 1-4,A/B 对比 req/s 与 p99 |
65 | | -``` |
66 | | - |
67 | | -## 6. M2 验收对照(spec 17) |
| 43 | +## 5. M2 验收对照(spec 17) |
68 | 44 | | AC | 状态 | 说明 | |
69 | 45 | |---|---|---| |
70 | | -| 构建/启动 | ✅ | lib+server 编译通过(-Werror),DPDK 注册成功 | |
71 | | -| AC-F1 ff_zc_recv 全链路功能 | ⏸ 阻断 | 数据面 VPC 投递失效(差分证明非代码问题)| |
72 | | -| AC-M1/M2 内存安全(mempool/valgrind)| ⏸ | 需数据面恢复后跑流量验证 | |
73 | | -| AC-P1 单核性能 A/B | ⏸ | harness 就绪,待数据面恢复采集 | |
74 | | -| 代码正确性(编译/符号/启动/差分)| ✅ | 与 baseline 行为一致,未引入回归 | |
75 | | - |
76 | | -## 7. 合规 |
77 | | -- ✅ 停进程走 kill_process.sh;清 rtemap/临时文件走 rm_tmp_file.sh;无直接 rm/kill/chmod |
78 | | -- ✅ 未臆造任何性能/功能数据;http=000 如实记录 |
79 | | -- ✅ client 命令经 ssh 下发 |
| 46 | +| 构建/启动 | ✅ | clean 重编译后 -Werror 通过;DPDK 注册 | |
| 47 | +| AC-F1 ff_zc_recv 全链路功能 | ✅ | curl http=200 size=438(5/5)| |
| 48 | +| AC-F4 普通 recv 零回归 | ✅ | A(ff_read) 同样 http=200 正常 | |
| 49 | +| AC-P1 单核性能 A/B | ✅(已采集)| 小包 echo 下持平;大 payload 收益待专测 | |
| 50 | +| AC-M1/M2 内存安全 | ⏳ | T1/T2/T3 共 ~400 万请求无崩溃;valgrind/mempool 精确计数待补(DPDK 运行态 valgrind 成本高)| |
| 51 | + |
| 52 | +## 6. 合规 |
| 53 | +- ✅ 停进程走 kill_process.sh;清 rtemap/stale .o 走 rm_tmp_file.sh;**修复了此前一次误用 `rm -rf` 的违规**(已改用脚本)。 |
| 54 | +- ✅ 未臆造数据;http=000→根因→修复→http=200 全程实测;性能离群值如实标注并复测校正。 |
| 55 | +- ✅ client wrk 命令经 ssh 下发(复用已有 /tmp/wrk/wrk,未重复安装)。 |
| 56 | + |
| 57 | +## 7. 后续 |
| 58 | +- AC-M(内存安全精确化):大 payload 长跑 + rte_mempool_in_use_count 前后对比。 |
| 59 | +- 大 payload 性能专测以体现 ZC-recv 设计收益。 |
0 commit comments