# 近期研发与优化工作 · PPT 补充材料(含完整实验材料)

> 实验机 `ubuntu@cuda-ke`(AMD Threadripper PRO,192 线程),AFL++ 4.40c,clang/LLVM 18。
> 下载站 **http://down.kew.ac/**。本页附全部实验数据与脚本(见文末〔附〕),可复现。
>
> **一条主线**:D5③ 相位计时证明 **worker 的瓶颈是 showmap 去重,不是 Z3 求解**。据此我们
> (A)评估了"换更快求解引擎(SymSan)"——结论是**低 ROI,因为求解不是瓶颈**;(B)转而**直接优化 showmap 去重**,
> 落地三项优化并提交。

---

## 一、工作概览

| 工作 | 内容 | 产出 |
|---|---|---|
| **A. SymSan 迁移评估** | 评估把 concolic 引擎换成 R-Fuzz/SymSan 的代价与收益 | 决策:**不替换**(详见 `SymSan_迁移评估.md`) |
| **B. showmap 去重优化** | 照 D5③ 瓶颈,三项优化 + 端到端验证 | 3 次提交,`showmap_dedup_优化.md` + `exp_showmap/` 数据脚本 |
| C. 支撑性修复 | 使能消融 + 修一个真 bug | 2 次提交 |

**提交记录**(分支 `mpi-parallelism-and-quality`,GitHub `kilb/symcc`):
| commit | 说明 |
|---|---|
| `62dae7e` | run_benchmark:修 showmap `batch_timeout` 大语料溢出(sqlite 168 万 TC → `OverflowError`) |
| `5570eeb` | mpi_fuzzing_helper:`SYMCC_EMIT_HINTS` 改可被 env 关闭(使能技术③消融) |
| `ba95e8b` | mpi_fuzzing_helper:内容级预去重(跳过字节相同输出的 showmap) |
| `ee4d03c` | mpi_fuzzing_helper:批量 showmap(-I)+ 跨 item 去重 + CPU 亲和核实 |

---

## 二、SymSan 迁移评估(决策：不替换)

**结论:代价 ≈ 6–10 人周,收益低——SymSan 的卖点(求解快/省内存 ~10–40×)恰恰优化的是本项目数据已证"不卡"的环节。**

| 维度 | 当前 SymCC | R-Fuzz/SymSan |
|---|---|---|
| LLVM | 18 | 18.1.18 ✅ 同代(唯一好消息) |
| 机制 | `_sym_*` 符号表达式树 → QSYM → Z3(108 API) | DFSan 影子内存 label 传播 |
| 运行模型 | 二进制自驱,写 `SYMCC_OUTPUT_DIR` | 需 FastGen driver / 作 AFL++ mutator |
| C++ 目标 | 支持 | 进程内 Z3 不推荐(须 FastGen) |

代价:引擎层丢弃 ~16.8k 行 vendored qsym,自研技术①–⑤ 需重写 ~1,170 行(①②难);编排层 ~90% 可复用。
**为何低 ROI**:#1 消融显示增强让生成量 ×12 → 覆盖 +0pp;D5③ showmap 占 worker 53%、Z3 才 46%;D1 并行度 >64 递减。
→ 求解速度非瓶颈。完整分析见 **`SymSan_迁移评估.md`**。

---

## 三、showmap 去重优化(三项)

### 3.0 瓶颈定位(D5③ 数据)
worker 对 SymCC 每个输出:读内容 → showmap 取边 → 并入位图判新。showmap 去重占 worker 时间 **np8 40% / np32 53%**,
且 #10 量化 **~80% 输出冗余**。这是"换 SymSan 也不解决"、但可低成本啃的真瓶颈。

### 3.1 优化① 内容级预去重(含跨 item)· commit `ba95e8b`+`ee4d03c`
**实测:SymCC 单次 concolic 输出里约 23–28% 字节完全相同**(见〔附〕表 T1)。字节相同→边集必然相同→dedup 结果
必与首次相同(**不可能判新**)→**直接跳过昂贵的 showmap**。
- 键=16B blake2b 摘要;集合为 **worker 生命周期有界集**(`worker_seen`,上限 30 万,兼吃 item 内+item 间重复)。
- 正确性:首次已并入 worker 位图,重复项 merge 必"非新",跳过等价;计入 `redun["byte_dup"]`,#10 漏斗保持精确。

### 3.2 优化② 批量 showmap(`afl-showmap -I`)· commit `ee4d03c` 〔本轮最大头〕
把一个 item 全部(预去重后)唯一输出的 showmap,从**逐个流式 get_edges**(Python 每次管道往返)改成
**一次 `afl-showmap -I filelist -o mapdir`**——整个 forkserver 循环在 **C 里**跑,免 Python 逐次开销。
- **隔离实测 ~25 us/输入 vs 流式标称 ~600 us/输入 ≈ 24×**(见〔附〕表 T2)。
- 失败(不支持 -I/报错)→ **自动退回流式**;开关 `SYMCC_BATCH_SHOWMAP`(默认开)。
- **端到端 A/B(诚实)**:np=32 各 2 轮,showmap 绝对耗时 **流式 31.18s → 批量 28.65s = −8%,但 n=2 分布重叠、
  在噪声内、覆盖持平**(见〔附〕表 T4)。**单轮曾显 −29% 是流式那轮 37.4s 偏高的假象,多轮后基线降到 31s**。
  **24×/输入 端到端几乎没兑现**:该相位里 showmap 调用只是一部分,还含读几百输出 + merge(两路共享),
  且 1 item/worker 方差极大(exec 37↔79s)掩盖小幅收益。→ **批量正确+覆盖中性+每次调用确实快,但端到端不显著;
  稳的收益是 #1 减调用数。** 批量作默认开+流式回退保留(慢目标/高争用时更可能显效),不作主要性能卖点。

### 3.3 优化③ CPU 亲和(核实:已由现有钉核覆盖)· commit `ee4d03c`
- 现有 `SYMCC_CPU_LIST`(`_compute_symcc_cpu_list`,门槛 AFL 实例≥16)把 SymCC rank 钉到与 AFL 互斥的保留核,
  **worker 派生的 afl-showmap 子进程(流式+批量)都继承该亲和** → 已被钉核。
- D5③ 里 np=32 **已开钉核仍增长到 53%** → 残余争用是**内存带宽/LLC**(单 NUMA 多 worker 并发 showmap),
  **非核迁移,亲和治不了**。**批量(②)每 item 一次 afl-showmap 而非几百次,才是缓解带宽争用最有效的一招。**
  故不另加亲和代码(避免过度工程)。

---

## 四、完整实验材料〔附〕

### 表 T1 · 字节重复率(优化① 依据)
| 场景 | 输出数 | 字节重复 | 占比 |
|---|---|---|---|
| gfts-xml 12 种子(池化) | 4,729 | 1,314 | 27.8% |
| gfts-xml 微基准 | 1,349 | 315 | 23.4% |
| run_symcc_worker seed_01 | 225 | 62 | 27.6% |
| run_symcc_worker seed_02 | 524 | 151 | 28.8% |
→ 稳定在 **23–28%**。脚本:`exp_showmap/microbench.py`。

### 表 T2 · 批量 vs 流式 per-input(优化② 依据,隔离微基准)
| 方式 | 每输入 | 备注 |
|---|---|---|
| 逐个流式 get_edges | ~600 us | 代码文档标称(Python 每次管道往返) |
| **批量 afl-showmap -I** | **25–51 us** | N=3000→25us,600→31us,400→51us |
→ **约 24×**。脚本:`exp_showmap/batch_bench.py`。

### 表 T3 · `run_symcc_worker` 端到端隔离(优化①②正确性,无 MPI)
| 种子 | gen | interesting | 去重耗时 | byte_dup | 漏斗自洽 |
|---|---|---|---|---|---|
| seed_01 | 225 | 91 | 0.10s | 62 | ✓ reported+infeasible+worker_fresh+showmap_none+byte_dup=gen |
| seed_02 | 524 | 177 | 0.17s | 151 | ✓ |
→ 批量生效(0.1–0.17s,非流式回退的 ~5s/输出),漏斗精确,临时目录零残留。

### 表 T4 · 端到端 A/B(优化② 实效,profiled hybrid,lava-base64,120s,showmap 绝对秒数)
**np=32 各 2 轮(消噪后的诚实数)：**
| 配置 | 每轮 | 均值 | 覆盖(均值) |
|---|---|---|---|
| 流式(b0) | 34.04 / 28.31 | **31.18s** | 23.53% |
| 批量(b1) | 31.69 / 25.61 | **28.65s** | 23.44% |
→ 均值 **−8%**,但 **n=2 分布重叠(b1_r1 31.7 > b0_r2 28.3)→ 在噪声内、非显著**;覆盖持平。
单轮 np8/32 参考(方差大):b0_np8 10.82 / b1_np8 10.48;b0_np32 37.37 / b1_np32 26.41(该 37.4s 为离群,故单轮"−29%"不可信)。
数据:`exp_showmap/batch_ab_2round.csv` + `batch_ab_summary.csv` + `phase_timing_*.csv`。脚本:`batch_ab.sh`/`batch_ab2_cont.sh`。

### 表 T5 · 目标非确定性探测(解释 A/B 覆盖 ±1pp 抖动)
gfts-xml 在 afl-showmap 下,**同一字节内容连续两次 → 边集不同的样本 = 3/5**(对称差 1–11 条,因超时/持久态)。
→ 说明 baseline 本身对同语料就不可复现,批量的 ≤1pp 差异在目标自身抖动内。脚本:`exp_showmap/determinism_probe.py`。

### 实验脚本清单(`exp_showmap/`,均可复现)
| 脚本 | 用途 |
|---|---|
| [microbench.py](http://down.kew.ac/exp_showmap/microbench.py) | 字节重复率 + 去重相位隔离计时 |
| [batch_bench.py](http://down.kew.ac/exp_showmap/batch_bench.py) | 流式 vs 批量 per-input 对比 |
| [batch_ab.sh](http://down.kew.ac/exp_showmap/batch_ab.sh) | 端到端 A/B(profiled hybrid,batch 开/关 × np8/32) |
| [determinism_probe.py](http://down.kew.ac/exp_showmap/determinism_probe.py) | 目标非确定性探测 |
| [batch_ab_summary.csv](http://down.kew.ac/exp_showmap/batch_ab_summary.csv) | A/B 汇总 |
| phase_timing_b{0,1}_np{8,32}.csv | 各 run 六相位原始计时 |

---

## 五、诚实的局限与后续
- **优化② 的端到端收益经多轮核实后是"小且在噪声内"(np=32 各 2 轮:31.18→28.65s,−8%,分布重叠)**,
  单轮的 −29% 是流式离群轮造成的假象。**profile 方差极大**(1 item/worker,exec 37↔79s),要更硬的显著性需更多轮 +
  更多 item/worker(如加长 timeout 让每 worker 处理多个 item)。
- 优化②的 24×/输入是**隔离**数;端到端被"读几百输出 + merge 共享段 + 大方差"稀释,**几乎未兑现**——故我们
  **不把批量作为主要性能卖点**;它正确、覆盖中性、带回退,保留为默认开(慢目标/高争用时更可能显效)。**稳的收益是 #1 减调用数。**
- 全量 MPI 端到端此前反复被基础设施打断,**根因已定位**:`pkill -f "run_benchmark.py"` 匹配到自身 shell 命令(自杀);
  改用精确进程名清理后干净跑通。
- 相关背景材料:`SymSan_迁移评估.md`、`showmap_dedup_优化.md`、D5③ 相位计时(`05c_phase_timing_np*.csv`)、
  #10 冗余拆分(`07_redundancy_and_constraints.md`)。
