增加可选性能埋点并完成物性效率评估

This commit is contained in:
ljz committed 2026-08-16 17:46:04 +08:00
1 parent 4e0b9fd8cc
commit 57b459bc72
21 files changed
+2029 -179

No files matched your search

+5
View File
@@ -9,6 +9,11 @@
- [更新日志 2026-08-15](更新日志-2026-08-15.md)
## 求解与性能
- [后端求解逻辑与效率优化调研](后端求解逻辑与效率优化调研.md)
- [仿真性能评估 2026-08-15](仿真性能评估-2026-08-15.md)
## 模型开发
1. [组件模型建模规范 v1](component-model-authoring-spec-v1.md)
+119
View File
@@ -0,0 +1,119 @@
# SystemSimulationApp 仿真性能评估(2026-08-15)
> 代码基线:`model-development@6a06489`,随后只加入本报告所述的可选埋点和基准工具。
> 本次评估的是前端流式接口实际使用的 System XML 求解路径;所有时间均为本机实测,不代表其他机器的绝对性能。
## 1. 结论
1. **压力—流量闭合是当前首要热点。** 深度审计中,三个气动短算例有 71%~85% 的计时落在 `PressureFlowSolver.solve()` 的包含时间内。它同时包含残差组装及其触发的物性调用,不能与物性时间相加。
2. **物性调用存在很高的完全相同输入重复率。** 按每次代数闭合重置精确输入影子集合后,空气链路、空气分支和氦气阶跃的重复率分别为 91.2%、96.5% 和 82.3%。空气公式很便宜,不能只凭重复率加缓存;Peng–Robinson 氦气更值得优化。
3. **现有两项氦气 LRU 精确缓存有效。** 冷缓存审计中,`properties_from_mU` 命中率 95.5%,`temperature_from_pressure_enthalpy` 命中率 78.6%;21 次配对端到端测试中,暖缓存比每次清空缓存快约 7.9%。这些缓存已经存在于评估基线,本次没有新增或改变缓存算法。
4. **长仿真的时间主要花在积分阶段。** 10 s 氦气均压算例耗时约 10.6~11.5 s,其中标准埋点测得积分占 90.5%,初始化约 4.2%,逐采样点后处理约 5.0%。
5. **结果 JSON 暂不是这些算例的首要矛盾。** 四个短算例的最终 NDJSON 结果约 29~59 KiB,编码中位数约 0.4~1.2 ms;501 个采样点的长算例约 507 KiB,编码约 18.5 ms。
6. **首次仿真有明显冷启动。** 新 Python 进程第一次短算例约 0.71 s,预热后同类算例约 0.06~0.13 s。剖析表明首次进入 SciPy 求解路径的惰性导入占了主要差额;这是服务首请求延迟,不是稳态吞吐。
7. **用户提供的 demo XML 尚不能形成完整性能样本。** 它仍在 `0.000175 s` 左右因 `Initial guess is outside of provided bounds` 失败;深度埋点确认错误发生在压力—流量闭合。本批只记录失败路径,没有顺带改变求解器容错行为。
## 2. 埋点实现与污染控制
性能开关由进程启动环境变量 `SIMULATIONAPP_PROFILE` 决定:
| 模式 | 用途 | 记录内容 | 适合场景 |
| --- | --- | --- | --- |
| `off` | 正常运行,默认值 | 不在响应中加入性能数据;装饰器在模块加载时直接返回原函数 | 正式仿真和最终性能对比 |
| `standard` | 低开销阶段统计 | XML 校验、网络编译、系统构造、初始化、积分、后处理、结果组装 | 日常定位“大阶段” |
| `audit` | 深度审计 | 再展开 RHS、代数闭合、压力流量、stream、刷新、导数和物性内核 | 短算例诊断、调用频率与缓存评估 |
一次运行使用一个 `ContextVar` 隔离的 `PerformanceTrace`,不会把不同仿真任务的阶段计数混在一起。成功或失败的求解结果在 profiling 模式下都会把快照放入 `diagnostics.performance`。主要字段为:
- 阶段:`calls`、`inclusiveNs`、`selfNs`、`maxNs`、`errors`;
- 物性:上述时间字段,以及介质、操作、缓存查询/命中/未命中;
- audit 专有:闭合内精确输入唯一数/重复数、逆解迭代总数/最大值/收敛与未收敛次数;
- `propertyOutermostNs`:只累计最外层物性调用,避免把嵌套 PR 内核时间重复相加。
标准模式只保留低频的大阶段计时。21 次氦气阶跃配对运行中,标准模式相对关闭模式的中位开销为 1.9%;四个短算例分开校准为 0.5%~2.9%。audit 会逐次生成精确指纹并计时,短算例可慢到约 2.5~5 倍,因此 audit 数据用于定位和计数,最终优化收益必须回到 `off` 模式复测。
将当前代码的 `off` 模式与备份提交 `6a06489` 同时运行 21 次氦气阶跃,墙钟中位数差为约 0.3%,处于本机噪声范围。也就是说,默认关闭时没有观察到稳定的热路径退化。
## 3. 测试方法
环境:Windows 11、Python 3.12.3、SciPy 1.18.0、64 位 Intel 处理器。仓库没有 PyInstaller/Nuitka 等可执行文件构建链,本次直接使用项目实际启动后端的 `.venv-win` 解释器。把同一 Python 代码再包成单文件只会混入解包和启动成本,不会使这里的求解内核更接近生产路径。
基准工具入口:
```powershell
.venv-win\Scripts\python.exe -m app.simulation.benchmark_performance `
--mode audit --warmups 1 --runs 3 `
--factory "helium_step=tests.test_amesim_pnvo001_signal_xml:high_pressure_helium_step_project" `
--output app/data/performance-evaluations/helium-step.json
```
工具默认传入取消检查回调,从而走与前端流式仿真相同的低层逐步积分路径。它记录墙钟、进程 CPU、最终 NDJSON 编码、输入 SHA-256 和完整性能快照。原始 JSON 写入被 Git 忽略的 `app/data/performance-evaluations/`,避免把机器相关的大量样本提交到仓库。
本次代表算例:
| 算例 | 内容 | 暖机后 `off` 墙钟中位数 | 重复次数 |
| --- | --- | ---: | ---: |
| `air_chain` | 空气气缸—节流孔—管路—储罐 | 62.4 ms | 9 |
| `air_branched` | 空气分支网络 | 130.3 ms | 9 |
| `helium_step` | 高压 PR 氦气、信号阶跃阀 | 65.2 ms | 9 |
| `mechanical_contact` | MECMAS21/LSTP00A 弹性接触 | 33.0 ms | 9 |
| `helium_long` | 10 s PR 氦气均压、501 个输出点 | 10.63 s | 1 |
短算例先暖机 2 次再测 9 次;缓存 A/B 使用两个同时启动的独立进程各暖机 5 次、测量 21 次,以尽量抵消瞬时系统负载。长算例只测 1 次,因此它只用于判断数量级与阶段占比。
## 4. 深度阶段结果
下表时间是 audit 中位数,会包含审计自身开销;调用数和相对热点比绝对时间更可靠。
| 算例 | RHS | 完整闭合 | 压力流量求解 | 压力流量包含时间占 audit 总时间 | 物性调用 | 闭合内精确重复率 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| `air_chain` | 33 | 37 | 74 | 77.0% | 4,265 | 91.2% |
| `air_branched` | 23 | 26 | 56 | 84.6% | 7,378 | 96.5% |
| `helium_step` | 79 | 102 | 235 | 71.2% | 11,121 | 82.3% |
| `mechanical_contact` | 74 | 78 | 156 | 29.5% | 0 | 不适用 |
当前热流耦合不是旧文档所写的固定 2~3 次压力求解。每次闭合先做 1 次压力求解,然后最多执行 25 轮 `stream → pressure-flow` 固定点;也就是说理论上最多 26 次。本次四个算例的平均压力求解次数/闭合分别为 2.00、2.15、2.30 和 2.00。优化时应编译依赖/脏标记并减少不必要的全网 pass,但不能直接删除第二轮,否则会重新引入求值历史依赖并破坏有限差分 Jacobian。
## 5. 物性调用与缓存结果
氦气阶跃的冷缓存 audit 代表运行:
| 操作 | 调用 | 命中/未命中 | 命中率 | 真实逆解次数 | 平均迭代 | 最大迭代 | 未收敛 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| `properties_from_mU` | 1,930 | 1,843 / 87 | 95.5% | 87 | 3.99 | 5 | 0 |
| `temperature_from_pressure_enthalpy` | 398 | 313 / 85 | 78.6% | 85 | 5.00 | 5 | 0 |
暖机后以相同配置重复运行,这两项在代表快照中均为 100% 命中,说明当前精确 LRU 能跨同配置运行复用确定性轨迹。关闭埋点的端到端配对结果为:暖缓存中位数 77.05 ms,每次清空缓存为 83.69 ms;换算为暖缓存约快 7.9%。
audit 的自身时间排序还显示:`isentropic_density_pressure_factor` 调用 398 次,`density` 业务入口及 PR 密度内核各调用 1,198 次,PR `compressibility_roots` 调用 1,200 次。同一 `(p,T)` 周围存在“等熵因子内部求密度,随后流量公式再次求密度”的重复机会。这里应优先复用同一闭合内的精确结果或合并 API;不要用四舍五入/容差键缓存,否则会在残差函数中制造平台并影响 ODE/least-squares 的有限差分。
空气算例虽然精确重复率更高,但理想气体公式本身只有少量算术。对这些廉价函数增加字典查询可能比重算更慢,应先做专门 A/B,不应套用氦气结论。
## 6. 输出与失败样本
| 算例 | 最终结果大小 | NDJSON 编码中位数 |
| --- | ---: | ---: |
| `air_chain` | 29.2 KiB | 0.39 ms |
| `air_branched` | 59.1 KiB | 1.21 ms |
| `helium_step` | 55.5 KiB | 1.10 ms |
| `mechanical_contact` | 51.4 KiB | 0.62 ms |
| `helium_long` | 507.4 KiB | 18.48 ms |
用户 demo 的输入 SHA-256 为 `27048a99da0a21922d75785b760c3b5d04be3349b8aef6fbfedfd811d87ef1d5`。audit 失败运行记录到 80 次 RHS、83 次闭合、165 次压力流量求解,最后一项各有 1 次错误;这与此前定位的低压试探态越过 `least_squares` 初值边界一致。由于没有到达 10 s 终点,不能把其 1.08 s 失败耗时当作完整模型性能。
## 7. 后续优化顺序
1. **先优化压力流量执行计划。** 继续预编译组件/连接残差归属、显式赋值顺序和热流耦合脏标记;增加快路径命中率、非线性 `nfev` 累计耗时,区分“全网扫描慢”与“非线性迭代慢”。
2. **再减少 PR 物性重复。** 复用组件当前 `(m,U,V)` 的状态恢复结果,合并等熵因子与密度读取;沿用精确键、有界容量和按仿真隔离原则。现有 LRU 已带来约 8% 的短算例收益,不应回退。
3. **处理冷启动。** 若首请求延迟重要,可在 worker 启动时显式导入 SciPy 求解模块或运行一个极小、无业务副作用的预热模型;不要把约 0.65 s 冷启动归因到每次仿真。
4. **长算例再看后处理复用。** 当前代表长算例的积分占 90.5%,所以积分/闭合仍优先;当采样更密或变量更多时,再评估复用已接受状态闭合、按需变量和降采样。
5. **把 demo 数值容错作为独立修复。** 统一压力可行域与初值投影、将试探态错误转为可恢复拒步,并在闭合前刷新外部容积缓存;该改动需要单独回归,不能混入性能优化提交。
## 8. 本次评估边界
- 没有固定 CPU 亲和性或关闭后台程序,短算例绝对时间存在数毫秒波动,因此以中位数和配对实验为主。
- audit 会显著改变廉价函数的单次耗时;不能把 audit 的物性毫秒数直接当成关闭埋点后的真实占比。
- 当前 LRU 命中/未命中来自调用前后的全局 `cache_info()` 差值;本报告均为单任务运行。多个 audit 仿真线程同时调用同一缓存时,阶段/物性调用仍按 trace 隔离,但缓存命中差值可能交错,不能用来做并发结论。
- 直接抛出 `HTTPException` 的校验/执行异常会结束 trace,但当前不会把快照附到错误响应;demo 属于返回 `failed` 部分结果的路径,所以本报告能够取得其失败快照。
- 本批没有测峰值 RSS、1/2/4 并发吞吐、浏览器解析/绘图或 8/32 单元拓扑扩展曲线。
- 没有为评估引入新的近似缓存、容差调整或求解器算法变更;所有性能结论都与数值优化改动解耦。
+36 -36
View File
@@ -1,7 +1,7 @@
# SystemSimulationApp 后端求解逻辑与效率优化调研(通俗版)
> 调研基线:2026-08-12(System XML v3 迁移后),依据当前仓库代码、配置、说明文档与测试。
> 本文所称“主求解路径”是当前前端实际调用的 System XML 流式接口;固定 TestModel 和 Test MQL 接口另行说明。文中没有把静态代码分析冒充 CPU、内存实测。
> 调研基线:2026-08-15(System XML v3 迁移后),依据当前仓库代码、配置、说明文档、测试与阶段埋点。
> 本文所称“主求解路径”是当前前端实际调用的 System XML 流式接口;固定 TestModel 和 Test MQL 接口另行说明。机器相关的实测结果单独见[仿真性能评估 2026-08-15](仿真性能评估-2026-08-15.md)。
## 0. 三分钟读懂
@@ -74,7 +74,7 @@
1. **[已实现] 当前主内核是“半显式 ODE + RHS 内代数闭合”。** 动态组件只把储能状态交给 ODE 积分器;每次计算导数前,系统先传播信号、刷新热力状态、求压力/流量代数网络、传播变容边界、迭代 stream 焓并更新机械加速度。它不是通用 DAE 求解器,也不等价于完整 Modelica `inStream/actualStream` 语义(`README.md:18-20`、`app/simulation/README.md:174-195`)。
2. **[已实现] 当前前端主链路是 System XML 流式仿真。** 浏览器生成 XML,经 `POST /api/system-xml/simulate-stream` 发送;后端以 NDJSON 返回心跳与进度,最后在一个 JSON 行中返回完整结果。不是 WebSocket 或标准 SSE。
3. **[已实现] XML v3 的 `sampleStep` 是输出采样间隔,不是固定积分步长。** 内部的 `max_step`(XML 为 `maxStep`)才是自适应积分步长上限;`BDF/Radau/LSODA/RK45/RK23/DOP853` 均受支持。流式运行因总是提供取消检查,会使用 SciPy 低层求解器逐个已接受步推进。
4. **[已实现] 每次 RHS 的完整闭合至少调用 2 次、存在外部容积传播时最多调用 3 次压力流量求解。** 积分结束后,每个输出采样点又执行一次完整闭合并提取全部公开结果。这是当前最明确的单任务重复工作来源。
4. **[已实现] 每次完整闭合先调用 1 次压力流量求解,再执行最多 25 轮 `stream → pressure-flow` 固定点。** 因而每次闭合至少 2 次、理论上最多 26 次压力求解;本次代表算例平均为 2.00~2.30 次。积分结束后,每个输出采样点又执行一次完整闭合并提取结果。
5. **[已实现] 代数求解已有因果化快路径。** 压力流量求解器预编译相等组与显式流量计划,种子残差足够小时不调用非线性优化;否则对全局未知向量调用 SciPy `least_squares`,当前未提供解析 Jacobian 或 `jac_sparsity`。
6. **[已实现] 当前启动脚本是一个 Uvicorn worker。** 每个流式任务再创建一个无并发上限的 daemon 线程和无界队列;没有进程池、集中任务队列、CPU/内存配额或持久化作业系统。同步仿真端点还会在 `async def` 中直接执行 CPU 密集代码。
7. **[推断] 优化应分两条线:**
@@ -205,30 +205,25 @@ stream 焓 `h_outflow` 不直接强制相等;标量信号和气动外部容积
- 气体携带的能量按实际流向交给下游;
- 若还有机械活塞或控制信号,它们在同一时刻也要一致。
代码目前不是一次对完,而是按固定顺序做若干轮专项检查。因此一个“计算变化率”的请求会调用 **2 次压力/流量闭合**;涉及外部容积传播时会调用 **3 次**。这也是后文首要优化方向。
代码目前不是一次对完,而是先建立初始压力解,再让 stream 焓和压力—流量相互迭代到同一个固定点。这样做是为了让当前 RHS 不依赖上一次调用留下的焓/流量历史,并保持有限差分 Jacobian 可重复。
`GenericFluidSystem._close_current_state()` 的实际顺序见 `app/simulation/systems/generic.py:258-290`:
`GenericFluidSystem._close_current_state()` 的实际顺序见 `app/simulation/systems/generic.py`:
| 顺序 | 操作 | 目的 |
| ---: | --- | --- |
| 1 | `SignalResolver.solve(time)` | 更新时间信号源并从 output 传播到 input |
| 2 | 刷新动态组件热力端口 | 由当前 `m/U/V` 恢复压力、温度、焓等 |
| 3 | 第一次 `PressureFlowSolver.solve()` | 闭合当前压力、流量、机械端口代数关系 |
| 4 | `PneumaticVolumeResolver.solve()` | 沿气动连接传播外部 `volume/volume_flow` |
| 5 | 若发生容积传播,再刷新热力状态并第二次求压力/流量 | 让变容边界进入气室状态关系 |
| 6 | `StreamResolver.solve()` | 按实际流向迭代传播/混合 `h_outflow` |
| 7 | 无条件再次求压力/流量 | 让依赖 stream/温度的构成关系重新闭合 |
| 8 | 更新机械约束加速度 | 为机械状态导数准备 `a` |
| 2 | 传播机械 `x/v` 等值关系 | 把当前机械状态同步到刚性连接端口 |
| 3 | `PneumaticVolumeResolver.solve()` | 沿气动连接传播外部 `volume/volume_flow` |
| 4 | 刷新动态组件热力端口 | 由当前 `m/U/V` 和最新体积恢复压力、温度、焓 |
| 5 | 第一次 `PressureFlowSolver.solve()` | 建立本轮热流固定点的初始压力和流量 |
| 6 | 最多 25 轮 `StreamResolver.solve()` 后再求压力流量 | 让焓、温度引用和构成流量同时收敛;按流量变化判停 |
| 7 | 更新机械约束加速度 | 为机械状态导数准备 `a` |
随后 `rhs()` 才收集各动态组件的导数(`app/simulation/systems/generic.py:298-301`)。
随后 `rhs()` 才收集各动态组件的导数。
因此:
因此每次闭合至少有 **2 次**、最多有 **26 次**压力流量求解。外部容积传播会影响初始热力状态,但不再用“有没有容积传播”直接决定固定次数。stream 自身仍有相对容差 `1e-9` 和最多 100 次内部迭代;外层热流固定点最多 25 轮,两层上限不能混为一个数。
- 无外部容积传播时,每次闭合固定有 **2 次**压力流量求解;
- 有外部容积传播时固定有 **3 次**;
- stream 默认相对容差 `1e-9`、最多 100 次迭代,每轮复制端口焓并扫描组件/端口(`app/simulation/solvers/stream.py:29-119`)。
**[发现]** 这套固定顺序没有按模型实际能力裁剪。例如没有信号、没有外部容积源或 stream 不反向影响构成关系的网络,仍经过对应全网 pass。是否能安全删去某一 pass 必须由依赖关系和回归测试决定,不能只凭某个算例结果不变。
**[发现]** 这套顺序仍没有按模型实际能力完全裁剪。例如没有信号、没有外部容积源或 stream 不反向影响构成关系的网络,仍经过对应全网 pass。是否能安全删去某一 pass 必须由依赖关系、脏标记和回归测试决定,不能只凭某个算例结果不变。
## 6. 初始化、积分参数与推进方式
@@ -256,7 +251,7 @@ stream 焓 `h_outflow` 不直接强制相等;标量信号和气动外部容积
| `sampleStep`(内部 `sample_step`) | 默认 `0.1 s` | 仅生成输出 `t_eval` 采样网格;工程 JSON 仍暂名 `simulation.step` |
| `maxStep`(内部 `max_step`) | 默认 `0.005 s` | 自适应求解器内部已接受步的上限 |
| `method` | 默认 `BDF` | BDF、Radau、LSODA、RK45、RK23、DOP853 |
| `rtol` | 通用 XML 路径硬编码 `1e-5` | 外层 ODE 相对误差;用户不可配置 |
| `rtol` | 通用 XML 路径硬编码 `1e-6` | 外层 ODE 相对误差;用户不可配置 |
| `atol` | `SolveIVPConfig` 标量默认 `1e-8` | 同时用于不同量纲的全部状态;用户不可配置 |
| `first_step` | 默认 `None` | 交给 SciPy;用户不可配置 |
| 代数残差容差 | `1e-7` | 压力流量快速路径/接受标准 |
@@ -331,9 +326,9 @@ STEP0、UD00 等信号源提供离散事件时刻。积分器先推进到事件
- stream 最大迭代数;
- 停止状态及部分错误上下文。
**[发现]** `_close_current_state()` 中局部变量 `algebraic` 会被后续 pass 覆盖;最大残差/评估统计只采集每次闭合最后一次压力求解,而 `solveCount` 才累计了全部调用。现有响应还没有外层积分 `nfev/njev/nlu`、接受/拒绝步、重启次数、分阶段墙钟时间、热物性调用数、峰值 RSS、队列深度和结果字节数。
**[已实现]** 积分诊断已经包含分段及汇总的 `nfev/njev/nlu`、已接受步、求解器启动、状态迁移和可恢复重试数。设置 `SIMULATIONAPP_PROFILE=standard|audit` 后,响应还会加入分阶段墙钟时间;audit 进一步记录物性调用、精确重复、缓存命中和逆解迭代。
因此本文可静态定位重复工作,但不能用现有诊断精确量化每个热点的时间占比。
**[发现]** `_close_current_state()` 中局部变量 `algebraic` 会被后续 pass 覆盖;最大残差/评估统计只采集每次闭合最后一次压力求解,而 `solveCount` 才累计了全部调用。仍缺少压力快路径命中率/累计 `nfev`、峰值 RSS、任务队列深度等服务级指标。结果字节和编码时间目前由离线基准工具测量,不进入常规 API 响应。
## 9. 求解时前后端交流
@@ -440,11 +435,11 @@ O(组件 + 连接 + 代数结构)
| 热点 | 代码证据 | 影响范围 | 判断 |
| --- | --- | --- | --- |
| 每次闭合固定 2~3 次压力流量求解 | `generic.py:258-290` | 每个 RHS、初始化、每个结果采样点 | [已实现] 重复 pass;真实耗时待测 |
| 每次闭合执行 2~26 次压力流量求解 | `generic.py` 的热流固定点 | 每个 RHS、初始化、每个结果采样点 | [实测] 代表气动算例平均 2.00~2.30 次;audit 包含时间占 71%~85% |
| stream 每轮复制/扫描并重复刷新 | `stream.py:29-119` | 每个闭合,最多 100 轮 | [已实现];网络越大越明显 |
| 非线性回退用全局有限差分 least-squares | `algebraic.py:927-947` | 快速路径失效时 | [已实现];大非线性网络潜在陡增 |
| 外层刚性积分器看不到显式稀疏 Jacobian | `solver.py:528-1009` | BDF/Radau 的每步/Newton | [已实现] |
| 热物性重复反算 | `mediums.py:199-266` 及各动态组件 refresh | 每个 RHS/闭合 pass | [推断] 需调用计数确认 |
| 热物性重复反算 | `mediums.py` 及各动态组件 refresh | 每个 RHS/闭合 pass | [实测] 闭合内精确重复率 82%~97%;PR 氦气缓存端到端收益约 8% |
| 每采样点完整后处理闭合 | `generic.py:397-474` | 输出点 × 全网 | [已实现] |
| 每个已接受步构造 dense output | `solver.py:528-914` | 流式逐步路径 | [已实现];无跨样本/事件时可能浪费 |
| 无界求解线程与任务结果驻留 | `main.py:491-520, 773-880` | 并发任务 | [已实现] 稳定性风险,不等于单算例变慢 |
@@ -452,7 +447,7 @@ O(组件 + 连接 + 代数结构)
## 13. 优化建议排序
以下按**预期综合收益**排序;同档位优先低风险、低难度项。收益是基于调用频率与复杂度的代码推断,不是基准测试结果。“单算例”指一个模型的墙钟时间,“吞吐”指多任务服务能力。
以下按**预期综合收益**排序;同档位优先低风险、低难度项。排序同时参考代码结构和 2026-08-15 的阶段/物性实测,但尚未覆盖大规模拓扑与多任务吞吐。“单算例”指一个模型的墙钟时间,“吞吐”指多任务服务能力。
### 13.1 先看人话版
@@ -460,7 +455,7 @@ O(组件 + 连接 + 代数结构)
| 顺序 | 人话方案 | 为什么可能更快 | 主要风险 |
| ---: | --- | --- | --- |
| 1 | 少做重复“瞬时对账” | 当前每次变化率计算固定做 2~3 次压力/流量闭合,调用频率最高 | 少做一轮可能漏掉真实耦合,必须按组件依赖裁剪 |
| 1 | 少做重复“瞬时对账” | 当前每次闭合做初始压力求解和热流固定点,实测压力流量层最热 | 少做一轮可能漏掉真实耦合,必须按组件依赖和脏标记裁剪 |
| 2 | 先整理方程,再求解 | 合并重复未知量,把关联较弱的方程分组;大模型回退迭代时收益很高 | 连接、接触和跨域活塞会让分组出错 |
| 3 | 给不同状态使用合适的“尺子” | 质量、内能、位置、速度量级差异很大;合理缩放可减少无效内部步 | 容差改变会影响精度和事件时刻 |
| 4 | 相同输入不要重复查热物性 | 同一轮闭合中常以相同状态反算压力、温度等 | 缓存失效不严谨会产生错误结果 |
@@ -486,15 +481,13 @@ O(组件 + 连接 + 代数结构)
### 13.2 推荐落地顺序
在改算法前先增加低侵入观测,但不把“加指标”误列为直接加速:
低侵入阶段/物性观测、积分计数和代表算例首轮基准已经落地,但不把“加指标”误列为直接加速。下一步建议:
1. 记录每个闭合 pass 的调用数、墙钟时间、代数 `nfev` 与是否命中快路径;
2. 记录热物性调用数/迭代数、stream 迭代数;
3. 导出外层 `nfev/njev/nlu`、接受/拒绝步、事件与重启次数;
4. 记录状态/结果数组字节数、最终 JSON 字节、任务队列深度和进程 RSS;
5. 用小、中、大三类基准网络定位排名 1~5 的真实占比;
6. 先实施第 1、4、8、9 项的可回滚改造,再决定第 2、3、5 项的深度;
7. 服务并发需求明确后并行推进第 6、7 项。
1. 给压力流量层补快路径命中、累计非线性 `nfev` 和残差装配时间,继续拆解本次确认的首要热点;
2. 用同一套基准对执行计划裁剪、组件级精确物性复用做 `off` 模式 A/B;
3. 补 1/8/32 单元规模曲线、1/2/4 并发吞吐和峰值 RSS;
4. 记录状态/结果数组字节、任务队列深度;结果 JSON 字节可继续由基准工具测量;
5. 再决定代数分块/Jacobian、结果按需计算和进程 worker 的实施深度。
每项算法改动都应继续验证质量/能量守恒、正反流、stream 混合、机械端挡、信号断点、取消部分结果和 AMESim/TestModel 基线。相关测试证据包括 `tests/test_generic_system_xml_simulation.py:244-533`、`tests/test_core_solver.py:19-508`、`tests/test_amesim_mechanical_public_components.py`。
@@ -516,9 +509,14 @@ O(组件 + 连接 + 代数结构)
- 采样上限、超时、心跳和任务名义保留时长。
- 组件参数在单次运行中静态;时间变化通过信号源等模型表达。
### 推断及必须实测
### 已有初步实测、仍需扩大样本
- 压力流量闭合是当前代表气动短算例的首要热点;物性调用具有高精确重复率,现有 PR 缓存有可见端到端收益。
- 长氦气代表算例的积分阶段占约 90.5%,后处理约 5%。
- 上述结论仍需在更大拓扑、更多真实工程和固定硬件环境复测。
### 推断及必须继续实测
- 哪一类闭合 pass、热物性或 Jacobian 估计占主要墙钟时间。
- 单个任务实际占用几个核心、SciPy/BLAS 原生线程数和多任务扩展曲线。
- 典型/最大工程的峰值 RSS、结果 JSON 大小、浏览器内存副本和 sessionStorage 成功率。
- 各优化的实际收益;表中排序应在观测数据出现后更新。
@@ -537,6 +535,8 @@ O(组件 + 连接 + 代数结构)
| 气动外部容积 | `app/simulation/solvers/pneumatic_volume.py:21-93` | `PneumaticVolumeResolver` |
| 机械因果化与事件 | `app/simulation/solvers/mechanical.py:225-627` | `MechanicalStateReducer` |
| ODE 推进 | `app/simulation/solvers/solver.py:37-1009` | `SolveIVPConfig`、`integrate_ode()` |
| 可选性能埋点 | `app/simulation/performance.py` | `profile_run()`、`profile_phase()`、`profile_property()` |
| 可重复性能基准 | `app/simulation/benchmark_performance.py` | `python -m app.simulation.benchmark_performance` |
| 前端流式协议 | `frontend/src/App.tsx` | `streamSystemSimulation()`、取消/轮询 |
| 启动方式 | `start-backend.bat:17-21` | Uvicorn 单 worker 命令 |
| 主路径回归测试 | `tests/test_generic_system_xml_simulation.py`、`tests/test_core_solver.py` | 通用仿真、事件、取消 |