# 性能基准

基准通过公共 MoonBit API 测量普通归档解析、编辑写出、重名逻辑比较，以及共享嵌套 thin
容器的校验、物化和比较。输入在内存中确定性生成，每个场景都检查结果；失败不会生成成功报告。

## 运行

需要仓库固定版本的 MoonBit、native C 编译器和 Python 3.9+。从仓库根目录执行：

```sh
python tools/benchmark.py
```

脚本先构建 release native 驱动，再生成 `_build/verification/benchmark.json` 和同名 Markdown
表格。JSON 保留每次测量值、版本、Git 提交、工作区修改状态、操作系统、架构、工具链、
驱动 SHA-256 和完整参数。CI 在 Linux、Windows 和 macOS Apple Silicon 上执行同一矩阵，
报告随对应运行的 `verification-*` artifact 提供；发行报告附在 GitHub Release。

较短的本地检查：

```sh
python tools/benchmark.py --sizes 100,1000 --depths 1,4 --samples 2 --iterations 3
```

`--payload-bytes` 可设为 4..4096，成员数 3..10000、深度 1..16、样本数 1..20、每样本迭代数
1..1000。`--report PATH` 指定报告位置，`--moon PATH` 指定工具链。
`--benchmark PATH` 使用已有驱动，其构建配置记录为 `caller-provided`，由调用方保证来源。
`--cases` 可选择一个或多个场景，报告记录实际选择。例如单独比较两种名称分布：

```sh
python tools/benchmark.py --cases unique_compare duplicate_compare --sizes 10000 --samples 7 --iterations 20
```

## 场景与结果检查

默认成员数为 100、1000、10000，每成员 128 字节；嵌套深度为 1、4、16。共 39 组场景：

| 场景 | 计时操作 | 结果约束 |
| --- | --- | --- |
| `parse` | 解析已准备好的 GNU 普通归档 | 普通成员数准确 |
| `edit` | 从已解析归档建立编辑计划，替换中间成员、移动首项至末尾并写出 | 替换内容、移动位置和成员数正确，输出长度稳定 |
| `duplicate_compare` | 比较两个已解析归档；所有成员同名，反转顺序并改变一项内容 | 恰好一项内容变化、识别顺序变化、无配对歧义 |
| `unique_compare` | 比较两个已解析归档；每个成员名称不同，反转顺序并改变一项内容 | 恰好一项内容变化、识别顺序变化、无配对歧义 |
| `nested_validate` | 加载并检查整批嵌套成员 | 总内容长度正确，共享容器每批只加载一次 |
| `nested_materialize` | 加载并生成普通归档字节 | 成员数正确，完整输出与原始普通归档字节相同 |
| `nested_compare` | 加载 thin 快照并与预先生成的普通快照比较 | 内容与索引映射相同、顺序不变 |

嵌套每层包含同样数量的 archive-offset 引用，最底层是普通归档；深度表示外部容器加载次数。
加载器为内存映射，每次批量操作断言调用次数恰好等于深度，确保测量包含共享容器缓存路径。
累计记录预算显式设置为 `(成员数 + 1) × 深度`，其他预算使用库默认值。
`input_bytes` 是场景输入归档总字节数；嵌套场景包含根 thin 及所有依赖容器。

成员载荷是用于区分内容的确定性二进制数据，不是编译器对象。本基准衡量归档操作，
不衡量 ELF/Mach-O/COFF/bitcode 符号发现、磁盘读取或链接速度。

## 测量口径

- 每组启动 3 个独立进程；每进程先准备输入并检查语义，再预热 1 次、计时执行 3 次。
- MoonBit 单调时钟测量循环总耗时，除以迭代数得到每次操作耗时；表格报告三个进程样本的
  中位数、最小值、最大值。场景所列的操作内校验包含在计时中。
- 进程启动、编译、输入构造、完整输出预检查和 JSON 序列化不计入操作耗时。
- 内存是操作系统记录的**整个进程生命周期峰值驻留内存**，包含运行时、准备输入、预热和
  所有计时迭代；不是单次操作新增内存、分配总量或 GC 堆大小。表格取样本中最大的峰值。
- Windows 读取 `PeakWorkingSetSize`；Linux 将 `ru_maxrss` 的 KiB 转为字节；macOS 的
  `ru_maxrss` 直接为字节。每轮先在独立进程触碰 64 MiB 内存，检查单位；该探针不进入计时进程。

共享 CI 主机的调度、系统版本和编译器都会影响结果。比较改动时，应固定主机、工具链、
参数与构建配置，并查看原始样本波动。CI 检查结果正确、测量有效和单位一致，不以固定耗时
作为通过门槛，也不把跨平台差值解释为库本身的性能提升。
