apsis-rs/docs/design/bench.zh.md

186 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 压测方法与报告
[English](./bench.md) | 简体中文
本文件记录压测的方法学与实测数据,使他人能够复现并判断结论是否可信。
## 方法学
### 三种测量,分别回答不同问题
| 工具 | 回答的问题 |
| --- | --- |
| `bench` | 单次调用有多快 |
| `bench_scale` | 成本随规模如何增长 |
| `bench_parallel` | 多个核心能省多少 |
三者都在 `apsis-rs` 门面中,以 example 形式提供,release 模式运行:
```bash
cargo run --release -p apsis-rs --features full --example bench
cargo run --release -p apsis-rs --features full --example bench_scale
cargo run --release -p apsis-rs --features full --example bench_parallel
```
### 三条原则
**无预热。** 每项测量前不丢弃任何一次调用。首次调用会付出惰性分配与缓存的代价,
而调用方等待的正是这个代价,把它藏在一次被丢弃的运行里,等于报告了一个没有人
真正等待过的数字。因此 `bench_scale` 同时给出**冷启动**与**稳态**两列。
**取多次最优。** 串行基线跑若干次取最快。调度抖动只会让某一次变慢,不会让所有
次都变慢;取最快得到的是干净的信号,而不是被邻居进程污染的下界。`bench_parallel`
用这一方式。
**报告每单位成本。** 绝对值随机器变化,`ns per unit` 不变。看后者才能判断复杂度
是否正确。
### 复杂度判据
对输入规模 n,`ns per unit` 恒定即 O(1) 每单位(线性总时间);`ns per unit`
按 n 的幂增长即该幂次的总复杂度。指数由相邻两点的比值取对数得到。
## 测量环境
| 项 | 值 |
| --- | --- |
| CPU | AMD Ryzen 7 8845HS(8 核 16 线程) |
| 内存 | 28 GB |
| 工具链 | rustc 1.98.1,release |
| 依赖 | 无第三方,基准为 example |
绝对值只在本机有意义。跨机器比较应看同一工具的**比值**。
## 结果一:单次调用
| 路径 | 每次调用 |
| --- | --- |
| Hermite 星历插值查询 | 24.3 ns |
| TEME 到地固系旋转 | 26.8 ns |
| 开普勒根数转状态 | 38.1 ns |
| 地固系转大地坐标 | 50.1 ns |
| 链路预算 C/N0 | 60.6 ns |
| SGP4 传播(历元后 30 分) | 248.7 ns |
| 可见性搜索(120 样本) | 7.49 μs |
| 规划 60 个任务(1 资源) | 239 μs |
星历查询比它所替代的 SGP4 传播快约十倍,这正是 `apsis-ephemeris` 存在的理由:
一次建表、多次查询时,插值远便宜于传播。
## 结果二:规模扫描
### 星座一日传播(60 秒步长,1441 样本/星)
| 星数 | 冷启动 | 稳态 | 每样本 |
| --- | --- | --- | --- |
| 24 | 8.7 ms | 8.7 ms | 252 ns |
| 240 | 80.5 ms | 80.0 ms | 231 ns |
| 1008 | 339.5 ms | 339.5 ms | 234 ns |
| **2016** | 679.4 ms | 679.4 ms | 234 ns |
**每样本成本恒定(增长指数 0.00)**,即 SGP4 单次传播是 O(1),总时间线性于星数。
两千余星的一日覆盖约 0.7 秒。冷启动与稳态几乎相同,说明该路径没有显著的
一次性分配。
### 可见性搜索(单站,每轨 2 小时)
| 轨数 | 每星 |
| --- | --- |
| 8 | 7.3 μs |
| 128 | 7.3 μs |
**恒定(增长指数 0.00)**,每条轨道独立,线性于星数。
### 拓扑构建与路由(4500 km 链路)
| 星数 | 每星 | 增长指数 |
| --- | --- | --- |
| 8 | 237 ns | — |
| 64 | 2.2 μs | 1.07 |
| 120 | 5.7 μs | 1.52 |
| 300 | 33.0 μs | 1.93 |
| **600** | **182.6 μs** | 2.47 |
**约 O(n²)**。每星成本随星数增长,指数从 1 升到 2.5。成因是几何判定本身
就是全对检查:n 颗星有 n² 对要判断。并行扫描证实瓶颈在此。
### 任务规划(单资源,50 长优先级链)
| 任务数 | 每任务 | 增长指数 |
| --- | --- | --- |
| 60 | 4.5 μs | — |
| 200 | 16.0 μs | 1.05 |
| 1000 | 108.4 μs | 1.33 |
| **2000** | **314.1 μs** | 1.54 |
**约 O(n²),大 n 时趋向 O(n)**。贪心放置本质上按时间序逐个安排,每次放置
都要与已放置的 placement 比较,故二次是算法本身而非实现缺陷。
## 结果三:并行扫描
### 传播(按卫星分块)
| 星数 | 1 线程 | 2 | 4 | 8 | 16 | 最佳加速 |
| --- | --- | --- | --- | --- | --- | --- |
| 550 | 184 ms | 1.96× | 3.83× | 6.86× | 8.12× | 8.12× (16) |
| 1000 | 336 ms | 1.89× | 3.73× | 6.49× | 8.24× | 8.24× (16) |
| 2000 | 671 ms | 1.89× | 3.74× | 6.61× | 7.93× | 7.93× (16) |
**传播是 embarrassingly parallel**:每个卫星独立,2 至 8 线程接近线性。
16 线程效率降到约 0.5,即超线程带来争用。**推荐 8 线程**(效率约 0.85),
或 16 线程换取更高绝对吞吐。
### 可见性搜索
| 轨数 | 1 线程 | 4 | 8 | 16 | 最佳加速 |
| --- | --- | --- | --- | --- | --- |
| 64 | 0.47 ms | 2.74× | 2.68× | 1.87× | 2.74× (4) |
| 256 | 1.95 ms | 3.52× | 4.36× | 5.27× | 5.27× (16) |
**小规模加速有限**,因为线程启动的固定开销在小工作量上占主导。256 轨约 5.3×。
### 拓扑构建(阶段拆分)
| 星数 | 可见性(可并行) | 边折叠(串行尾部) | 最佳加速 |
| --- | --- | --- | --- |
| 120 | 0.31 ms | 0.30 ms | 1.37× |
| 300 | 1.93 ms | 3.84 ms | 1.72× |
**该路径并行收益有限**。300 星时串行的边折叠占 3.84 ms,是可并行部分的两倍,
故总时间最多加速约 1.7 倍,远不及数值内核的接近线性。根因是 `add_edge` 查重时
线性扫描已有边,使插入本身成为 O(n³)。
## 结论
| 路径 | 复杂度 | 并行性 | 实用规模表现 |
| --- | --- | --- | --- |
| SGP4 传播 | O(1)/样本 | 优秀,16 线程 ~8× | 2016 星一日 0.68 s;16 线程 85 ms |
| 星历插值查询 | O(log n) | 随传播 | 24 ns/次 |
| 可见性搜索 | O(1)/星 | 良好,16 线程 ~5× | 256 轨 0.37 ms |
| 坐标与链路 | O(1) | 不必并行 | 27 至 61 ns |
| 任务规划 | ~O(n²) | 串行 | 2000 任务 0.63 s |
| 拓扑构建 | ~O(n²) | 收益有限(串行尾部主导) | 600 星 110 ms |
**要点**
1. **数值内核是线性且高度可并行的。** 两千余星的一日轨道预测单线程 0.68 秒,
16 线程 85 毫秒。
2. **星历插值比传播快十倍**,密集查询场景应先用传播建表再插值。
3. **两个组合算法受限于算法而非并行度**:任务规划是贪心的固有二次,拓扑构建的
边插入查重是二次的平方,后者并行化最多只能加速约 1.7 倍。欲再提升需改算法。
4. **传播推荐 8 线程**:并行效率约 0.85,16 线程因超线程争用降至约 0.5。
## 复现
```bash
# 全部门禁,确保测量的是正确代码
cargo test --workspace --all-features
# 三种测量
cargo run --release -p apsis-rs --features full --example bench
cargo run --release -p apsis-rs --features full --example bench_scale
cargo run --release -p apsis-rs --features full --example bench_parallel
```
测量之间不要并发运行其它负载。绝对值随机器变化,结论应基于同一工具内的比值。