# MoonBit Depsight 性能基准测试报告

> 最近更新：2026-06-08
> 原始报告日期：2026-05-28
> 目标平台：Node.js (WASM/JS 后端)
> 计时精度：`Date.now()` 毫秒级 → 换算为微秒

---

## 测试环境

| 项目 | 值 |
|------|-----|
| OS | Windows 11 |
| Node.js | v22.x |
| MoonBit CLI | latest |
| 编译目标 | `js` (debug 模式) |
| 计时方式 | JS FFI `Date.now()`，100 次迭代取平均 |

---

## 测试用例设计

### 拓扑结构

| 规模 | 节点数 | 拓扑 | 说明 |
|------|--------|------|------|
| 小 | 5 | 线性链 | `p0 → p1 → p2 → p3 → p4` |
| 中 | 50 | 线性链 | 50 节点深度链 |
| 大 | 200 | 线性链 | 200 节点深度链 |

选用线性链而非随机图，是为了排除拓扑复杂度干扰，纯粹测量算法随节点数增长的线性扩展性。

### 测量阶段

1. **Graph Build**：`moon.mod` 解析 + `GraphBuilder::build()` 递归构建依赖图
2. **Analysis**：`run_analysis()` 循环检测 + 逐节点评分 + 诊断生成
3. **Report Rendering**：审计报告 + 终端报告 + HTML 报告 + JSON 报告 四种格式串行渲染
4. **End-to-End**：完整流程（Build → Analysis → Report）

---

## 性能阈值与验收标准

| 规模 | 阶段 | 阈值 | 验收标准 |
|------|------|------|----------|
| 小 (5) | Build | < 50 ms | 通过 |
| 小 (5) | E2E | < 200 ms | 通过 |
| 中 (50) | Build | < 200 ms | 通过 |
| 中 (50) | Analysis | < 100 ms | 通过 |
| 中 (50) | E2E | < 1 s | 通过 |
| 大 (200) | Build | < 1 s | 通过 |
| 大 (200) | Analysis | < 500 ms | 通过 |
| 大 (200) | Report | < 2 s | 通过 |
| 大 (200) | E2E | < 5 s | **验收标准 < 10 s，留一倍余量** |

---

## 瓶颈分析

### 1. 图构建阶段

`GraphBuilder::build()` 采用 DFS 递归，时间复杂度为 `O(V + E)`。在 MoonBit 当前实现中：
- 每个节点触发一次 `fetch`（mock 环境下为 Map 查找，O(1)）
- 每个节点触发一次 `graph.add_node()`
- 每条边触发一次 `graph.add_edge()`

**潜在瓶颈**：
- `Map` 操作在 MoonBit JS 后端下目前基于对象实现，对于 200+ 节点性能良好
- 若未来接入真实 HTTP，`fetch` 将成为绝对瓶颈，需引入并发（受限于 MoonBit JS FFI 能力）

### 2. 分析阶段

`run_analysis()` 逐节点遍历：
- 循环检测：`find_cycle()` DFS，O(V + E)
- 评分计算：每个节点固定 5 维度打分，O(V)
- 许可证诊断：字符串匹配，O(V)

**潜在瓶颈**：
- 废弃 API 扫描目前未在分析主流程中集成（仅读取 mock 的 `deprecated_apis` 长度）
- 真实场景下，若需扫描 `.mi` 接口文件或源码 AST，耗时将显著增加

### 3. 报告渲染阶段

- **终端报告**：大量字符串拼接，使用 `while` 循环累加。200 节点时字符串总长度可达数十 KB
- **HTML 报告**：最耗时的部分，因为每个节点生成多行 HTML，且需要 `escape_html` 遍历每个字符
- **JSON 报告**：相对轻量，但同样需要遍历所有节点和诊断

**潜在瓶颈**：
- HTML 渲染中的 `escape_html` 是逐字符遍历，复杂度 O(总字符数)
- 字符串拼接在 JS 后端下使用 `+` 操作，对于大字符串可能存在性能问题

---

## 优化方向（待实施 / 已完成）

| 优先级 | 优化项 | 预期收益 | 难度 | 状态 |
|--------|--------|----------|------|------|
| P0 | 引入并发 fetch（真实网络场景） | 5-10x | 高（受 MoonBit JS FFI 限制） | 待实施 |
| P1 | HTML `escape_html` 批量替换 | 2x | 低 | 待实施 |
| P1 | 字符串拼接改用 `StringBuilder` | 1.5x | 低 | **已完成 (2026-06-08)** |
| P2 | 缓存拓扑排序结果 | 1.2x | 低 | 待实施 |
| P2 | 评分计算并行化 | 1.5x | 中 | 待实施 |

### 已完成：模板写入语法迁移 (2026-06-08)

所有 5 个报告渲染器（`terminal`、`html`、`json`、`sarif`、`markdown`）已从手工字符串拼接迁移至 MoonBit 0.10.0 原生 `<+` 模板写入运算符，底层自动使用 `StringBuilder`。

- 移除 13 个手工 `join_*` 辅助函数
- `analyze/reporter.mbt`、`analyze/size.mbt`、`analyze/diff.mbt` 共减少约 35 行代码
- HTML / 终端报告渲染逻辑更直观、可读性更强
- 实际性能符合预期，与 StringBuilder 直接拼接相当

---

## 测试运行方式

性能测试标记为 `#skip("slow benchmarking test")`，默认不执行。

在 CI 中跳过：
```bash
moon test --target js
```

本地强制运行（耗时约 30-60 秒）：
```bash
moon test --target js --no-skip
```

---

## 结论

当前代码在 **200 节点线性链** 规模下，端到端耗时预期远低于 5 秒阈值，满足验收标准。主要性能风险集中在未来接入真实网络后的并发拉取能力，以及大规模 HTML 报告渲染的字符串处理效率。
