优化原生结果编码传输与浏览器缓存,记录八路性能基线

原生结果series通过字节索引直传,C端使用Ryu精确回读编码和64 KiB批量写出;网页采用Float64缓存和CSV工作线程,减少结果处理与保存等待。

补充八路AME曲线核查、全流程分阶段计时、独立编码基准和复现工具,固定后续优化采用修正八路及rtol=1e-8。C写出1.1808→0.1638 s,点击到可查看8.0100→6.9756 s。

验证:最终10项编码专项、29项相关后端回归通过;8份原生结果逐位一致,16次网页结果/CSV/刷新恢复通过。前端构建及缓存/CSV专项在本轮结果处理工作中通过。环境、原始大结果与临时构建不纳入Git。
This commit is contained in:
lujingze committed 2026-09-11 15:09:15 +00:00
1 parent 808c484f5b
commit 3bc4be3c06
55 files changed
+20522 -141

No files matched your search

@@ -0,0 +1,156 @@
# C 端结果编码与写出优化(2026-09-11)
针对上一轮 [八路全流程成本评估](八路网页求解全流程成本评估-2026-09-11.md) 中约1.18 s的C结果写出阶段,先比较编码和缓冲方案,再实现并验证真实网页路径。案例固定为 [test-mql-8-corrected.json](../../tests/data/test-mql-8-corrected.json),未修改方程、局部管流求根、积分器、误差限、采样或前端生产代码。
已采用 **Ryu精确回读编码 + 64 KiB批量写出**。真实八路模型中,C编码写出墙钟中位数 **1.1808 → 0.1638 s,减少86.13%**;网页点击到结果可查看 **8.0100 → 6.9756 s,减少12.91%**,点击到浏览器缓存保存完成 **8.1280 → 7.0841 s,减少12.84%**。CSV下载保存没有观察到改善(1.1127 → 1.1506 s)。数值精度和求解路径保留,完整原生结果逐位一致,16次网页结果/CSV/刷新恢复核验通过。
上述网页收益是构建缓存命中的三次正式运行组中位数比较。首次编译另列:新依赖会增加冷编译成本,不能把缓存命中收益直接套用到首次运行。
## 调研与方案选择
原路径对约179万个结果数字逐值调用 `fprintf("%s%.17g", …)`。CPU时间与墙钟接近,只说明这一段主要在执行代码,仍需实验区分转换和写入成本。保留JSON合同可以继续使用已有Python原始片段传输、浏览器解析、缓存、CSV和结果文件流程。
候选比较基于作者源码与官方文档,未采用第三方性能宣传作为本项目的加速证据:
| 候选 | 本轮判断 | 一手依据 |
|---|---|---|
| 加大stdio缓存,保留 `fprintf %.17g` | 改动小;必须实测是否能减少主要成本 | 当前 `native/runtime/main.c` 与下方重放实验 |
| `snprintf %.17g` 到固定块,再 `fwrite` | 仍使用相同浮点转换;可隔离stdio调用方式的收益 | 下方重放实验 |
| Ryu binary64 shortest | 采用;C接口、小型固定依赖、无分配转换,能精确回读原浮点值 | [固定版本源码](https://github.com/ulfjack/ryu/blob/4c0618b0e44f7ef027ebae05d2cc7812048f7c8f/ryu/d2s.c)、[作者说明](https://github.com/ulfjack/ryu/tree/4c0618b0e44f7ef027ebae05d2cc7812048f7c8f)、[边界测试](https://github.com/ulfjack/ryu/blob/4c0618b0e44f7ef027ebae05d2cc7812048f7c8f/ryu/tests/d2s_test.cc) |
| yyjson 的Schubfach路径 | 可用作后续对照,但完整 `.c/.h` 约756 kB,本轮不引入完整JSON库 | [0.13.0接口](https://github.com/ibireme/yyjson/blob/6447536015f3d600f3d65323b10976103b337ca7/src/yyjson.h#L1715-L1733) |
| 独立yy_double / Dragonbox | 前者属于作者基准仓库抽出版;后者官方实现要求C++11,本轮保留C11构建链 | [yy_double](https://github.com/ibireme/c_numconv_benchmark/tree/bdacf3330e202d7ec3ae552419ea5772bae95dac/vendor/yy_double)、[Dragonbox](https://github.com/jk-jeon/dragonbox/blob/beeeef91cf6fef89a4d4ba5e95d47ca64ccb3a44/README.md) |
Ryu 的最短转换指足以恢复原始binary64的有效数字,不代表完整JSON字符数一定最少。其裸接口也会生成 `NaN`/`Infinity`;这些不是标准JSON数字,因此包装层必须明确拒绝,而非直接输出。相关规则见 [Ryu源码](https://github.com/ulfjack/ryu/blob/4c0618b0e44f7ef027ebae05d2cc7812048f7c8f/ryu/d2s.c)、[RFC 8259 §6](https://www.rfc-editor.org/rfc/rfc8259.html#section-6)。
本轮固定Ryu提交 `4c0618b0e44f7ef027ebae05d2cc7812048f7c8f`,原样保留相关C/头文件,选择Boost-1.0许可。源码及来源清单位于 [native/encoding/ryu](../../native/encoding/ryu/),头文件位于 [native/include/ryu](../../native/include/ryu/),许可同时随原生构建的 `THIRD_PARTY_NOTICES.txt` 分发。它是项目源代码依赖,不是本地运行环境;未安装新环境或新增Python/前端依赖。
## 独立编码与写入实验
将真实八路原生结果的全部series、final和finalState,共 **1,790,486个binary64**,在计时外转为预加载的连续double数组。每个候选预热一次、正式三次,顺序交替,先写真实文件并逐值按64位模式核对,再单独做 `/dev/null` 输出对照。
计时从 `fopen` 前到 `fclose` 后,包含编码、缓冲设置和写出;不含输入加载、输出投影、JSON静态键名准备或数值复核,也未调用 `fsync`。连续数据重放不包含生产代码的跨行矩阵读取,不能直接将微基准加速当作网页提速。
| 编码/写入候选 | 真实文件墙钟 / s | 真实文件CPU / s | `/dev/null`墙钟 / s | 输出字节 |
|---|---:|---:|---:|---:|
| 原 `fprintf %.17g` | 1.121005 | 1.120823 | 1.108461 | 32,725,281 |
| `fprintf` + 1 MiB stdio缓存 | 1.121927 | 1.121777 | 1.107086 | 32,725,281 |
| `snprintf %.17g` + 64 KiB批量 | 1.148625 | 1.148510 | 1.087661 | 32,725,281 |
| 裸Ryu + 64 KiB批量 | 0.100643 | 0.100637 | 0.071845 | 34,387,794 |
加大stdio缓存没有改善;保留相同浮点转换的 `snprintf` 批量方案反而稍慢。裸Ryu重放墙钟减少91.02%,且 `/dev/null` 中同样大幅加速,证据支持主要成本在浮点转换,而非仅文件写入等待。CPU/墙钟之差不是独立磁盘耗时。
裸Ryu总是采用科学计数法,重放文件反而增大约5.08%。因此生产包装层进一步比较普通与科学表示长度;下方生产C写出包含该重排和真实stride读取,不能与裸Ryu的0.1006 s混作同一测量。
原始依据:[replay/summary.json](../../test/c-result-encoding-20260911/replay/summary.json),每次真实文件与计时记录均保留在 `replay/file/`。工具:[benchmark_native_result_encoding.py](../../tests/manual/benchmark_native_result_encoding.py)。
## 实现
- [json_numbers.c](../../native/runtime/json_numbers.c) 调用 `d2s_buffered_n`,用固定64 KiB栈缓冲批量写出数组,支持原输出矩阵的stride;每次调用返回前将自身缓冲交给FILE,保留调用者已有的stdio顺序和 `ftell` 边界。
- Ryu输出后只进行十进制token重排:普通表示更短时采用普通表示,否则保留科学计数法。例如 `1.2E1 → 12`、`1E-1 → 0.1`;等长时不改。重排没有浮点运算或再次舍入,也不会展开巨大指数。负零固定输出 `-0.0`,普通Python JSON读取也能保留符号。
- [main.c](../../native/runtime/main.c) 中 `series/final/finalState` 接入新编码。状态/整数计数/索引元数据、字符串转义、`--probe/--init` 的既有stdio路径保持原方式;不是所有C数字出口都改成Ryu。
- 非有限结果数字、短写、`ferror` 或 `fclose` 失败都会阻止新结果索引发布并返回失败。数值数组未写完整时,不能把已写出的文件前缀视作成功结果。活动runner仍要求每次使用新的输出目录。
- [build.py](../../app/simulation/native_codegen/build.py) 递归纳入嵌套头文件哈希,Ryu源码、查找表和许可记录都进入构建身份或随构建分发;不会误用优化前缓存。
JSON的字段、变量键名、列序、采样数和数值精度保留。数字拼写和文件SHA允许变化;不要求与旧 `%.17g` 的文本逐字相同。没有采用降低精度、减少采样、删列或有损压缩。
## 真实八路网页验证
输入SHA256为 `670977bef67e62d9c66e8af497bada208bd72a7301be45128d185d47282cf288`;157元件、178条连接、132状态、1784变量及时间列、1002个采样。0~10 s、0.01 s输出、CVODE BDF、`rtol=1e-8`、`max_step=1e30`及各状态atol下限保持原值。
旧版是本轮修改前从工作区冻结的代码(含此前结果传输/IDB/CSV优化),不是退回Git的旧后处理。旧版与新版各有无插桩组和阶段诊断组;每组预热一次、正式三次,串行运行。没有在正式计时期间安排其他大型构建、仿真或全量数值比对。前端全部使用相同生产资产,不改源码或构建。
用户端到端加速取同机无插桩两组;C写出细分取阶段诊断两组。页面“结果可查看”为成功完成DOM且按钮恢复可用,“保存完成”为IndexedDB事务提交后恢复指针发布的观察点。下载计时包括Playwright通知和 `saveAs`;本机回环HTTP不能代表远程网络。
三次正式运行的**中位数(最小~最大)**,单位s。端到端来自无插桩组,C阶段来自独立诊断组;各组依次采集,未声称同序号是交替配对试验。降幅统一为两组中位数之比,小样本、系统调度与温度波动仍影响结果。
| 指标 | 优化前 | 优化后 | 用时变化 |
|---|---:|---:|---:|
| C编码写出(墙钟,诊断组) | 1.1808(1.1529~1.2007) | 0.1638(0.1625~0.1671) | -86.13% |
| C编码写出(CPU,诊断组) | 1.1804(1.1528~1.1991) | 0.1638(0.1625~0.1671) | -86.12% |
| 点击运行 → 结果可查看 | 8.0100(7.9657~8.0463) | 6.9756(6.9228~6.9863) | -12.91% |
| 点击运行 → 缓存保存完成(观察点) | 8.1280(8.0499~8.1684) | 7.0841(7.0053~7.0849) | -12.84% |
| CSV点击 → 下载保存 | 1.1127(0.9959~1.3711) | 1.1506(0.8617~1.3136) | +3.41% |
| 结果文件点击 → 下载保存 | 1.2254(1.1259~1.3546) | 1.2662(0.9707~1.3405) | +3.33% |
| 积分求解(无插桩组) | 6.0926(6.0571~6.0992) | 6.0617(6.0598~6.0752) | -0.51% |
CSV和结果文件导出依然由已有浏览器路径生成,本轮未改。CSV用时波动范围重叠,不能判定加速;文件大小及SHA在全部16次运行间完全一致(31,820,845字节)。积分耗时的少量变化也不归因于编码:求解代码、计数和输出数值保持一致。
![C写出与网页等待时间对比](assets/2026-09-11/c-result-encoding-20260911-overview.png)
生产 `series` 字节数 **32,640,796 → 31,609,208(减少3.16%)**,诊断组HTTP响应体中位数 **34,475,145 → 33,442,734字节(减少2.99%)**。HTTP体另含元数据与进度,随时间文本略有波动;完整浏览器导出结果约33.85 MB,因浏览器重新编码而基本不变。
阶段诊断组的其他主要区间如下(单位ms,中位数):
| 阶段 | 优化前 | 优化后 | 边界说明 |
|---|---:|---:|---|
| 前端提交前预处理 | 18.800 | 22.600 | 模型检查、快照/XML生成及提交准备 |
| 后端XML校验 | 23.855 | 22.529 | 请求输入验证 |
| 网络编译 | 45.417 | 41.611 | 连接/方程编译 |
| 生成C | 59.194 | 60.283 | 生成模型代码 |
| 构建缓存校验 | 45.505 | 34.094 | 正式运行全部命中 |
| 积分求解 | 6113.293 | 5957.849 | 含积分器、RHS/Jacobian、事件和采样 |
| 输出投影 | 85.804 | 79.819 | 重算采样点输出,位于编码前 |
| C结果编码写出 | 1180.792 | 163.829 | 含fopen、编码、stdio、fclose及索引 |
| Python索引结果读取 | 46.351 | 40.434 | 父区间,含字节读取/小元数据解析 |
| HTTP结果事件组装编码 | 32.844 | 33.361 | 元数据JSON与原始series片段拼接 |
| 后端HTTP全程 | 7720.603 | 6553.295 | 包含上述后端子区间及ASGI发送等待 |
| 浏览器流文本解码 | 27.700 | 27.000 | 同步TextDecoder调用累计 |
| 浏览器结果JSON解析 | 99.700 | 104.300 | 单次原始JSON.parse |
C写出占原生 `main` 时间的比例从 **16.00%降至2.64%**;新版积分占 **96.05%**,输出投影约 **1.29%**。这里先计算每次运行的阶段/父区间比例,再取中位数。浏览器解析未见改善;下一步更大的速度空间仍在求解计算,结果侧剩余CPU时间已明显缩小。
首次运行单列(无插桩组,各一次,构建缓存未命中):
| 观察值 / s | 优化前 | 优化后 |
|---|---:|---:|
| 原生构建 | 3.6580 | 4.3720 |
| 点击到结果可查看 | 11.6815 | 11.3810 |
| 点击到缓存保存完成 | 11.8062 | 11.5025 |
本次新构建增加约0.714 s,抵消了大部分编码收益;首次页面运行仅缩短约0.30 s。这是单次冷构建观察,未做重复冷编译统计,不能推广为稳定冷启动提速。旧/新无插桩与诊断程序构建身份不同,均单独预热,不混入正式三次。
## 正确性、边界与限制
- 数字编码最终 **10项专项测试通过**。覆盖34,254个有限binary64位模式、正负零、极大极小/次正规数、十进制边界与随机值;默认及 `RYU_ONLY_64_BIT_OPS` 两种路径均逐位回读一致。覆盖64 KiB边界、stride、非有限值拒绝、短写/零写、`/dev/full` 与关闭失败。见 [最终测试日志](../../test/c-result-encoding-20260911/writer-final-tests.log)。
- 相关后端传输/取消、代码生成、HTTP、CSV与纯C后端 **29项回归通过**。该次同时运行当时9项数字编码测试,共38项;之后补充普通/科学token选择测试并重新运行最终10项编码测试。见 [回归日志](../../test/c-result-encoding-20260911/backend-tests.log)。
- 8次诊断原生结果以一份旧版为基准,其余7份全部 **1,790,486个数值逐位一致**,每份含1,044个负零;series、final和finalState均覆盖,不使用容差或抽样。状态和求解计数也相同,仅排除求解墙钟/CPU元数据。见 [native-bit-parity.json](../../test/c-result-encoding-20260911/native-bit-parity.json)。
- 16次真实网页完整series/final、CSV全部单元格、下载结果文件和刷新恢复通过;CSV比较 **28,617,120个单元格**,全部CSV SHA一致。网页比较是解析后的数值严格相等,原生64位检查另行补足负零验证。见 [equality.json](../../test/c-result-encoding-20260911/equality.json)。
- 原生CLI额外向 `/dev/full` 写出,返回退出码3且未发布结果索引。见 [写失败验证](../../test/c-result-encoding-20260911/write-failure-check/summary.json)。
- 所有网页运行均为1002采样、1784变量,nfev=74,265、接受步6,974、拒绝步454、njev=475、nlu=1,656、事件1、启动4。输入、导入导出参数/连接与前端资产哈希一致。
- 与本轮冻结源码比对,已有文件只改变C输出main、原生构建头文件扫描、README和许可;物理内核、积分器、代码生成方程、runner及前端生产资产未变。Ryu引入的C/头文件与Boost许可逐文件哈希等于固定上游快照。见 [source-manifest.json](../../test/c-result-encoding-20260911/source-manifest.json)。
本轮未改变数值求解算法,因此此前Amesim曲线差异结论保持不变。没有新的Amesim同工况CPU/墙钟数据,不作Amesim速度比较。源码兼容性考虑了GCC/MinGW,已在Linux GCC13.3实测默认及纯64位Ryu路径;本轮没有Windows运行实测。
后端输出期间仍包含输出投影;Python片段整理、传输、浏览器解析和保存也各有成本。父子区间及并行区间不能相加,独立阶段中位数不保证相加等于总耗时中位数。CSV生产实现本轮未修改,其下载用时差异仅记录为观察,不归因于C编码优化。
## 文件与复现
- 本报告:[C端结果编码与写出优化-2026-09-11.md](C端结果编码与写出优化-2026-09-11.md)。
- 所有原始产物:[test/c-result-encoding-20260911/](../../test/c-result-encoding-20260911/),Git忽略。
- 调研上游快照与SHA:[ryu-upstream/manifest.json](../../test/c-result-encoding-20260911/ryu-upstream/manifest.json);优化前冻结源码:[baseline-source/manifest.json](../../test/c-result-encoding-20260911/baseline-source/manifest.json)。
- 网页与后端汇总:[summary.json](../../test/c-result-encoding-20260911/summary.json)、[timings.csv](../../test/c-result-encoding-20260911/timings.csv)。
- 数字编码测试:[test_native_json_writer.py](../../tests/test_native_json_writer.py);传输与取消:[test_native_result_transport.py](../../tests/test_native_result_transport.py)。
当前优化版无插桩网页保留在 **http://127.0.0.1:8027/**,可导入同一八路JSON复查。计时数据、下载、截图、临时构建和上游调研快照都在被Git忽略的 `test/` 下;未安装新环境、提交或推送Git。源码Ryu依赖及许可应作为项目实现保留,不属于应忽略的本地运行环境。
仓库根目录运行。服务与浏览器应分两个终端启动,输出目录选新路径;下方只是新版复测例子,勿与其他仿真/编译并行。旧版重放使用 `baseline-source/tests/manual/backend_stage_profile.py`,显式 `--frontend-dist frontend/dist`;旧版诊断输出必须置于 `baseline-source` 内,以满足构建器的源码相对路径要求。
```bash
.venv/bin/python -m unittest tests.test_native_json_writer tests.test_native_result_transport tests.test_native_codegen tests.test_generic_system_xml_simulation tests.test_result_csv_export tests.test_native_only_backend -v
# 终端1:无插桩新版,新的端口和产物目录
.venv/bin/python tests/manual/backend_stage_profile.py --plain --port 8029 --output-dir test/c-encoding-recheck/backend
# 终端2:浏览器沿用已存在的本地运行条件
LD_LIBRARY_PATH="$PWD/.venv/native/browser-libs/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" .tools/node-v24.18.0-linux-x64/bin/node tests/manual/browser_stage_profile.mjs --url http://127.0.0.1:8029 --input tests/data/test-mql-8-corrected.json --mode control --runs 3 --output test/c-encoding-recheck/browser
```
诊断组去掉服务的 `--plain`,浏览器使用 `--mode profiled`;请另选新产物目录、端口并串行测试。独立编码实验、计时聚合和完整核对使用:
```bash
.venv/bin/python tests/manual/benchmark_native_result_encoding.py --result-json test/web-cost-20260911/native-compute-profile/control/run-1/result.json --output-dir test/c-encoding-recheck/replay --ryu-root test/c-result-encoding-20260911/ryu-upstream --run --warmups 1 --repeats 3 --dev-null
.venv/bin/python tests/manual/summarize_native_encoding.py --root test/c-result-encoding-20260911
.venv/bin/python tests/manual/compare_browser_stage_outputs.py test/c-result-encoding-20260911 --native test/web-cost-20260911/native-compute-profile/control/run-1/result.json --group baseline=test/c-result-encoding-20260911/browser-baseline --group baseline-profiled=test/c-result-encoding-20260911/browser-baseline-profiled --group optimized=test/c-result-encoding-20260911/browser-optimized --group optimized-profiled=test/c-result-encoding-20260911/browser-optimized-profiled --output test/c-result-encoding-20260911/equality.json
```
原生逐位工具 [compare_native_result_bits.py](../../tests/manual/compare_native_result_bits.py) 使用 `--baseline 旧结果.json --candidate 新结果.json --output 报告.json`,`--candidate` 可重复。准确输入路径记录于现有 `native-bit-parity.json`。图表由 [plot_encoding.py](../../test/c-result-encoding-20260911/plot_encoding.py) 用系统Python/matplotlib生成,可缩放图为 [overview.svg](assets/2026-09-11/c-result-encoding-20260911-overview.svg)。大结果数值核对安排在全部性能计时结束之后。
Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 111 KiB

@@ -0,0 +1,78 @@
# test-mql-8 当前 AME 归档与完整曲线核查
2026-09-11。只读解析当前输入、AME 归档和已完成的原生运行,不重新求解、编译或修改模型。
**当前八路归档的数据身份、公开参数和初始状态相互对应,可以作为已保存曲线的观察参考。完整曲线仍有差异,不能判为一致;Amesim 没有可信 CPU/墙钟耗时,速度比较明确 `skip`。** 归档名义容差为 1e-7,本轮原生为 1e-8,亦不构成同精度的性能比较。
## 本轮来源
| 文件 | SHA-256 |
|---|---|
| `tests/data/test_mql.ame` | `1ff0ea4284b9248260eeceb8b27cd0bc14dbccb43554ab8c0b49900d0b944c3d` |
| `tests/data/test-mql-8-corrected.json` | `670977bef67e62d9c66e8af497bada208bd72a7301be45128d185d47282cf288` |
| `test/mql8-efficiency-20260911/native-production/run-1/result.json` | `12a2018119c8f231056dfd834dfc9ac096945173f3982c98ee2b385140b2c7dc` |
本轮正式原生 run-1 已完整算到 10 s。其 `series`、`final`、`finalState` 与先前 `test/solver-newton-20260911/mql8/native-run-rtol1e8/execution/result.json` 逐值完全相同,比较产物已经绑定本轮 run-1。见 [逐值相等记录](../../test/mql8-current-archive-audit-20260911/native-result-equivalence.json)。
历史 `tests/baselines/simulation/test_mql_8/manifest.json` 绑定的是另一个 AME SHA:`cbc3aadd4569a49b3a63e5d66d4143ec16126c0f950df73fb637e07673c20fbb`。该旧基准不用于本轮。另一个现有 `test/mql8-efficiency-20260911/amesim-archive-comparison/comparison.json` 确实绑定当前 1ff0… 归档,但仅覆盖 140 条状态/阀流量曲线;本次补入碰撞力、限位力、间隙及原生额外事件采样。
## 归档是否自洽
归档成员均为 `test_mql_` 前缀,子文件 SHA 和字节数完整保存在 [comparison.json](../../test/mql8-current-archive-audit-20260911/comparison.json)。
| 成员 | 本次核查 |
|---|---|
| `.cir` | 117 个 COMP、40 个有子模型 LINE,157 个公开元件;以真实端口/接触/管线方向核对 corrected JSON 的全部 178 条连接、1092 个公开参数,均对应 |
| `.param` / `.data` | 各 1170 行;重新求值图纸与数据表中的表达式,1015 个直接绑定的公开参数均一致,2 个 LMECHN1 结构字段只保存在图纸 |
| 编译 `.c` | 声明 157 个子模型引用、132 个连续状态、24 个离散状态、1278 个变量;GParamInfo 对应全部 1170 行,1154 个具名参数所属模型可核对;1100 个具名 GVarInfo 的模型实例和变量名逐项匹配 `.var` |
| `.modelinfo` | 132 个连续状态、24 个离散状态,与编译 C 相同 |
| `.state` | 全部 132 个状态 Data_Path 与编译 C 的 GcontStateVarNum 顺序一致;其文件时间较旧本身没有造成状态错配 |
| `.var` / `.results` | 1278 个变量行,1116 个保存变量,1100 条具名曲线;1002 个严格递增时间点,覆盖 0–10 s,具名保存值均有限;132 个状态首点逐项对应当前 `.data` 初值 |
| `.sim` | 首行 `0 10 0.01 1e+30 1e-07 0.001 4 0.1`;不把未解码的求解器枚举位直接当作 CVODE/BDF 设置 |
| `.ameperf` | 仅包含 SC/DISC 的仿真时刻及事件计数,没有 CPU、墙钟或完整运行耗时 |
`.param` 的第 766、768、770、776 行将介质显示为 `PNGD_HELIUM instance 1`,编译参数表对应 `PNGD00 instance 1`;四行 Data_Path 均属同一 `pn_gas_data`,在审计中明确列作显示名别名。16 个 HIDDEN 参数行、82 个 HIDDEN 编译变量项没有伪造可读名称来宣称逐名核对。
这些检查未发现当前归档发生四路图纸/八路缓存错配,提供了使用其保存曲线的依据。它仍是归档中的历史运行,未在本轮观察 Amesim 重新运行,不能提供新的控制精度或耗时验收。
## 变量与误差口径
覆盖全部 132 个连续状态对应的物理量:56 条压力、56 条温度、10 条位移、10 条速度;另含 8 条阀流量、8 条接触力、20 条质量元件限位力和 8 条接触间隙,共 176 条曲线。
变量身份通过归档编译 C 的 GVarInfo/GcontStateVarNum、`.var` Data_Path 和图纸拓扑映射确定。单位来自对应 `.var` 标签与仓库保存的元件 C:PNVO001 的 `dm2` 保存单位为 g/s,乘 `-0.001` 转成本系统 port_2 的流入 kg/s;压力为表压 Pa,加 101300 Pa 转为绝对压力;温度 K、位移 m、速度 m/s、力 N 直接比较,间隙 mm 乘 0.001。见 [PNVO001.c](../../tests/data/AmesimModels/help/source/PNVO001.c) 中端口定义及末尾转换、[PNL0001.c](../../tests/data/AmesimModels/help/source/PNL0001.c) 中 `pa = p + PATM`。这些元件源文件用于解释单位,不作为另一个 AME 归档的数据参考。
LSTP00A 的归档 f2 明确为 f1 的重复量,8 组保存数组逐值相同;本系统两个接口力逐值反号。因此本文以 port_1.f 对 f1;port_2.f 对负 f2,得到相同误差。质量元件的 20 条 Fmin/Fmax 在双方保存点均为零,此项不能代替接触力检查。
对每一方的原始保存网格,分别将另一方原始曲线线性插值到该网格;不平移时刻、不平滑、不删除事件点。每条曲线输出最大绝对差、采样均方根差、最大差/参考峰值、RMS/参考 RMS,以及参考非零时的逐点相对差;参考为零的点另外保留绝对差。RMS 是所述采样网格上的等权 RMS。原生网格和归档网格分别报告,避免将没有保存的 Amesim 事件状态冒称为实测值。
## 保存点上的实际差异
下表是归档 1002 个保存点上的结果,每类列出最大绝对差所在曲线及该曲线 RMS;“峰值归一化”是该差除以该曲线参考峰值,不是逐点相对误差。
| 量 | 最差曲线 | 最大绝对差 | RMS 差 | 峰值归一化 | 最大差时刻 |
|---|---|---:|---:|---:|---:|
| 压力 | `amesim_pnl0002_6.p` | 163395.189 Pa | 7170.441 Pa | 0.792631% | 0.01 s |
| 温度 | `amesim_pnl0001_13.T` | 105.215279 K | 5.829065 K | 2.033444% | 0.01 s |
| 阀流量 | `amesim_pnvo001_7.port_2.m_flow` | 0.002990901 kg/s | 0.000114014 kg/s | 0.766320% | 0.04 s |
| 接触力 | `amesim_lstp00a_7.port_1.f` | 5131.970918 N | 225.217793 N | 0.796525% | 0.01 s |
| 接触间隙 | `amesim_lstp00a_2.gap` | 5.215260e-8 m | 2.265633e-8 m | 1.112982% | 1.27 s |
位移的最大绝对差为 `amesim_mecmas21_9.x` 的 53,857,561 m,RMS 为 52,430,984.93 m;该曲线参考终值本身为 7.68e15 m,所以不能脱离物理量级解读。该元件在双方均出现约 8e14 m/s 速度;当前 AME 的 UD00 输入含 1e17 的初始信号,不能把这种极端输入改小后再当成同模型验收。
各曲线按自身峰值归一化后,位移最差为 `amesim_mecmas21_5.x`:最大差 2.193606e-5 m、RMS 1.406520e-6 m、峰值归一化 0.00592859%;速度最差为 `amesim_mecmas21_10.v`:最大差 2.437279e-4 m/s、RMS 1.964328e-5 m/s、峰值归一化 0.00615392%。两者最大差在 0.98 s。全部逐曲线、逐网格统计见 [curve-differences.csv](../../test/mql8-current-archive-audit-20260911/curve-differences.csv)。
## 碰撞事件使完整曲线不一致
原生额外保存 `t = 0.9833956321732664 s`,170000 kg 的 `amesim_mecmas21_10` 此时到达 0.37 m 限位并将速度置零。8 个 LSTP00A 的原始接口力同时约为 **4.034997e11 N**。不能丢弃这一点后宣称完整曲线吻合。
归档在相邻 0.98 s、0.99 s 保存数据,没有这一事件时刻;将这两个点线性插值得到的接触力约 467936 N。以全部原生保存点为网格,最差接触力最大差为 **4.034993e11 N**,采样 RMS 为 **1.274703e10 N**。同一点,负载速度与归档插值差 2.615678 m/s、位移差 0.008950590 m。这些是保存曲线之间的差异,插值跨越限位事件,不能当作 Amesim 真实事件状态的误差。
双方保存的负载数据都显示限位发生在 0.98–0.99 s 内。归档 `.ameperf` 没有提供该负载在此区间的精确限位时刻;只有采样数据不足以确定两者精确事件偏移,也无法判断 Amesim 内部是否出现同类极窄接触峰。此前 0.01 s 的压力、温度、接触力误差发生得更早,不能全部归因于 0.9834 s 这一未对齐的保存事件。
因此本轮结论是“已完成全点差异观察,尚未通过八路曲线一致性验收”。未预设八路接受阈值,也未取得足够密的 Amesim 事件输出,不将这些差异自动判成精度达标。
## 耗时与复现
本轮原生 run-1 的纯求解墙钟为 5.797191 s、CPU 为 5.796605 s;这里只标识已有运行,完整性能分析由本轮优化总报告给出。归档中没有可用 Amesim CPU/墙钟记录。当前环境的 PATH、相关环境变量及 Python 模块检查亦未发现可调用 Amesim 安装;归档生成 C 标记为 Simcenter Amesim 2404,不等于当前可调用软件版本。不得用成员修改时间差或 `.ameperf` 的 10 s 仿真终点推算实际耗时,**Amesim 速度比较 `skip`**。
复现本次只读数值后处理:`.venv/bin/python test/mql8-current-archive-audit-20260911/audit_and_compare.py`。脚本输出来源/成员哈希、参数及状态身份、两种原始网格的误差、额外事件与未验收边界,不启动任何求解器。长期模型选择、先正确性后计时、固定精度及分阶段记录遵循 [优化验证约定](../standard/optimization-benchmark-model.md)。
@@ -0,0 +1,210 @@
# 八路模型计算效率与网页阶段计时(2026-09-11)
本轮以 `808c484` 的正式代码和 [test-mql-8-corrected.json](../../tests/data/test-mql-8-corrected.json) 为主案例。八路在当前默认精度下完整运行,未退回四路。本轮增加独立诊断脚本和运行记录,没有修改生产算法、工程参数或输出采样。后续遵循 [八路优先的优化验证约定](../standard/optimization-benchmark-model.md)。
## 运行范围与可复现条件
- 工程 SHA256:`670977bef67e62d9c66e8af497bada208bd72a7301be45128d185d47282cf288`;CLI XML SHA256:`2804b33f04cabb3c10fcc3cc0843c35de17efbe1b6ee5e5e821edd9a5515a23d`。对应 AME 为 `tests/data/test_mql.ame`,SHA256 `1ff0ea4284b9248260eeceb8b27cd0bc14dbccb43554ab8c0b49900d0b944c3d`。
- 157 元件、178 条连接、132 连续状态;返回 1784 个变量、1002 个原始采样点(含事件点),仿真 0~10 s,输出间隔 0.01 s。
- CVODE BDF / SUNDIALS 7.4.0,`rtol=1e-8`,`max_step=1e30`;自动首步。实际绝对误差限按状态生成:质量 `1e-14 kg`、内能 `1e-8 J`、速度 `1e-12 m/s`、位移 `1e-12 m`,并非对所有状态统一使用配置对象中的 `atol=1e-8`。数值雅可比、稠密线性求解和事件处理策略保持生产设置。
- Linux x86_64 虚拟机,Intel Xeon Silver 4210R @ 2.40 GHz,16 逻辑 CPU、约 30 GiB 内存;GCC 13.3.0、Python 3.12、Node 24.18.0、Chromium 151.0.7922.34。原生进程主要为单核计算,环境与构建哈希保存在原始记录。
- 各组预热一次、正式运行三次;中位数与范围单列。三算法组交错执行;网页对照组与分阶段插桩组串行执行,不同时运行诊断求解、绘图或大编译。样本数较少,组间百分之几的差异不作为显著优化结论。
## 管流算法效率与触顶情况
三算法使用同一 corrected 八路、物性复用实现和全系统积分精度。固定点版本仅在明确的 `5d5a2e1` 基线上恢复原半步松弛管流循环,其余生产数值逻辑保持一致;不是运行旧版整个应用。前次牛顿取自该提交,当前保护牛顿取自本轮正式内核。此组没有逐次调用计数插桩。
| 算法 | 纯求解中位数(范围)/ s | 进程全程中位数 / s | RHS 次数 | 接受 / 拒绝步 |
|---|---:|---:|---:|---:|
| 旧固定点,16 / 64 轮上限 | 12.0976(11.9926~12.1511) | 14.2514 | 119058 | 9647 / 679 |
| 前次牛顿 | 5.8183(5.7829~5.8944) | 7.9144 | 74265 | 6974 / 454 |
| 当前保护牛顿+二分回退 | 5.9138(5.9115~5.9323) | 7.9698 | 74265 | 6974 / 454 |
相对旧固定点,当前纯求解时间减少 **51.12%**、速度约 **2.05 倍**,进程全程减少 **44.08%**,RHS 次数减少 **37.62%**。相对前次牛顿,本组耗时增加约 1.64%,不能宣称保护机制带来额外提速;两版牛顿的完整采样、最终输出和状态逐值相同。
另用未经本轮插桩的正式构建独立运行一次预热、三次正式检查:纯求解中位数 **5.7972 s**(5.7897~5.8214),进程全程 **7.8504 s**(7.8437~7.8685),均完成 10 s;每次 RHS 74265、接受 6974、拒绝 454、雅可比 475、线性分解 1656、状态转换 1、求解器启动 4。该组构建缓存命中,输入准备 0.1493 s、构建/缓存核验 0.03294 s;这些准备时间在三个进程运行前发生一次,不包含在纯求解时间内。单独组的 5.80 s 不与上一组旧算法拼接计算加速比。
为区分算法本身和积分轨迹变化,另对三版内核进行独立计数诊断:先各自跑完整八路,再将当前轨迹的 **3,081,320 组实际管阻方程输入全部原样重放**给三个版本,不抽样、不去重。诊断耗时不用于上述性能比较。
| 同一组管阻输入的计数 | 旧固定点 | 前次牛顿 | 当前保护牛顿 |
|---|---:|---:|---:|
| 解析返回 / 迭代求解 | 0 / 3081320 | 2370685 / 710635 | 相同 |
| 累计循环轮数 | 49431317 | 3081555 | 相同 |
| 单次最多轮数 | 64 | 6 | 6 |
| 进入最后允许轮次 | 3037792(98.587%) | 0 | 0 |
| 耗尽额度且未满足各自停止条件 | 3010570(97.704%) | 0 | 0 |
| 实际返回值的统一相对残差 > 1e-9 | 3072455 | 0 | 0 |
| 二分回退 / 非有限返回 | 0 / 0 | 0 / 0 | 0 / 0 |
牛顿累计轮数减少 **93.766%**。710635 次迭代调用分别用 3 轮 74290 次、4 轮 361601 次、5 轮 236183 次、6 轮 38561 次。当前案例没有触发二分或失败路径,所以它验证了正常输入的效率和一致性,不能代替极端状态下的保护测试,也不能证明任意系统必然收敛。
“进入最后一轮”与“耗尽仍未满足条件”分开统计:固定点 PNL00R 的 64 轮分支有 1638 次进入最后一轮、但没有耗尽失败;真正耗尽的都来自其他管路的 16 轮分支。旧循环满足自身停止条件的 70750 次中,61885 次仍不满足当前统一方程残差门槛;相对残差超标不直接代表同等数量的大绝对流量误差。
各自完整积分轨迹上,旧固定点实际管阻调用 5041645 次、耗尽 4937544 次;两版牛顿均为 3081320 次、耗尽 0 次。零压差 247634 次和 PNL00R 直接层流 235766 次另计,未混入混合摩擦方程残差。当前插桩结果与独立正式构建的 `series/final/finalState` 逐值相同。
该八路在积分 RHS 中请求管流缓存 2970600 次,命中 **0**;另有 594120 次直接调用。物性复用与这项管流缓存不同;此结果只说明本例可进一步评估缓存查找的成本,不能直接推广到其他拓扑或据此删除缓存。
## 真实网页主流程与额外操作成本
使用正式 Vite 静态构建,经 Playwright 驱动 Chromium;无模拟 API、预制结果注入或重复读取响应体。独立对照服务 `127.0.0.1:8013` 不加载诊断插桩;分阶段服务 `127.0.0.1:8012` 仅在隔离 C 主程序中增加稀疏时钟,并包装实际后台函数。两个服务的求解器和元件文件逐字节相同,前端构建集合 SHA256 同为 `2faa6ce32ee9997187870d64af2bc235a830eb7b8def7749ddcb0eaeeed4831e`;计时脚本 SHA 也相同。
每组预热一次、正式三次。每轮从公开 JSON 导入入口加载同一 corrected 文件,公开导出工程后逐项验证全部参数、端点和仿真设置,然后点击运行;导入与核查不包含在点击运行计时中。每轮继续打开结果页、选择指定管路温度、下载 CSV 与结果文件,再刷新并核对恢复结果。结果页和温度曲线立即打开,允许浏览器 IndexedDB 异步保存与查看过程自然重叠。
下表单位为秒,格式为 **中位数(最小~最大)**。对照组是常规网页成本的主记录;“首次绘制机会”指可见 DOM 后经过两次 requestAnimationFrame,未测量 GPU 完成时间。
| 阶段 | 对照组 / s | 分阶段组 / s |
|---|---:|---:|
| 工程导入 change → 画布首次绘制机会 | 0.2527(0.2273~0.2862) | 0.2312(0.2251~0.2411) |
| 点击运行 → 完成状态 DOM | 9.8716(9.7697~9.8826) | 9.7777(9.7358~9.8408) |
| 点击运行 → 完成状态首次绘制机会 | 9.8989(9.7840~9.9104) | 9.8005(9.7596~9.8660) |
| 点击运行 → 结果页首次绘制机会(自动切页) | 10.1516(10.0600~10.1834) | 10.0589(10.0305~10.1056) |
| 点击运行 → 温度曲线首次绘制机会(自动选曲线) | 10.6899(10.5762~10.7431) | 10.6160(10.5916~10.6433) |
| 点击运行 → 观察到 IndexedDB 保存完成指针 | 12.2922(11.8303~12.4076) | 12.4344(11.5322~12.4967) |
| 进入结果页 → 首次绘制机会 | 0.1910(0.1893~0.1980) | 0.1927(0.1832~0.1946) |
| 选择温度 → 曲线首次绘制机会 | 0.0269(0.0262~0.0297) | 0.0276(0.0233~0.0293) |
| CSV 点击 → 下载并保存 | 5.6198(5.5717~5.6381) | 5.5732(5.4253~5.6625) |
| 结果文件点击 → 下载并保存 | 1.2308(1.2265~1.3213) | 1.2921(1.1552~1.5145) |
| 刷新导航 → 已恢复结果首次绘制机会 | 0.5885(0.5406~0.6592) | 0.5487(0.5074~0.5630) |
无插桩对照组的 C 纯求解中位数为 **6.0653 s**、进程全程 **7.9499 s**;独立 CLI 的 5.7972 s 属另一运行环境下的分组结果,不把差值直接归因于网页某项 CPU 工作。分阶段组点击到完成绘制为 9.8005 s,对照为 9.8989 s,相差约 -0.99%;本组三次样本未见明显端到端插桩增量,也不能把该负差当作加速。持久化和导出波动更大,逐次原始值均保留。
初次导航只记录每组一次:HTML `loadEventEnd` 对照 0.0971 s、分阶段 0.1086 s;Playwright 观察到工程导入控件时分别为 0.5628 / 0.6064 s,包含自动化观察与调度延迟,不是严格的首次可交互时间。首次工程导入到两帧观察点,对照预热为 0.3716 s;三次重复导入中位为 0.2527 s。页面加载、导入、仿真、查看与导出分别记录,未用自动化操作间隙拼成一个“纯网页耗时”。
“DOM 稳定”另取 120 ms 无变动再等两帧:结果页中位 0.3710 s、温度曲线 0.1736 s、刷新恢复 0.7575 s(对照)。这包含人为安静窗口,不能把它全称为渲染工作。下载完成包含 Playwright 通知、`saveAs` 与文件系统开销,不等于浏览器内序列化 CPU 时间。
## 后台内部各阶段
用每个请求的 `X-Simulation-Id` 将网页与后台记录一一关联。下表为分阶段组正式三次的秒数;所列主要阶段在单个请求内依次发生。各阶段分别取中位数,故其相加不保证等于总耗时中位数。
| 阶段 | 中位数(最小~最大)/ s |
|---|---:|
| XML 校验 | 0.0231(0.0222~0.0246) |
| 网络编译 | 0.0364(0.0361~0.0465) |
| 系统 C 代码生成 | 0.0542(0.0528~0.0548) |
| 构建缓存核验(3 次均命中) | 0.0321(0.0308~0.0331) |
| C 参数准备 | 0.0000503 |
| C 初始化与初始采样 | 0.0001(0.0001~0.0001) |
| C 纯积分 | 6.0855(6.0414~6.0994) |
| C 最终采样/状态处理 | 0.0000029 |
| C 最终及全采样输出投影 | 0.0855(0.0837~0.0861) |
| C 结果 JSON 格式化并写文件 | 1.1707(1.1656~1.1945) |
| Python 读文件并 UTF-8 解码 | 0.0360(0.0321~0.0429) |
| Python 解析原生 JSON | 0.5513(0.5429~0.5588) |
| 进程启动/等待/退出等未细分余量 | 0.0029(0.0025~0.0029) |
| 结果接口元数据组装 | 0.0330(0.0245~0.1175) |
| 最终 NDJSON 结果事件序列化 | 1.1928(1.1862~1.2106) |
| 序列化结束 → ASGI 最后响应体发送完成 | 0.1715(0.1489~0.1808) |
| HTTP 其余编排/调度余量 | 0.0124(0.0114~0.0155) |
后台 HTTP 全程中位 **9.5123 s**(9.4458~9.5845)。内部 C main 全程 7.3380 s,Python 原生执行与结果读取包装 7.9194 s,仿真 worker 全程 8.1380 s;这些是包含上表子阶段的父区间,**不能再次相加**。ASGI `send` 的累计 await 为 0.0701 s,可与生成结果的后台任务重叠,亦不代表客户端网络总时间。诊断产物保留另耗约 0.00066 s,已包含在原生执行包装中。
约 **2.95 s** 用于 C 的 JSON 写出、Python 读取解析及 HTTP 结果 JSON 序列化,约为后台总程的 31%;相比之下输出物理量投影仅约 0.086 s。这里先定位到文本结果处理成本,并未将整个差额笼统归为物性或求根。
正式网页八次运行均复用已构建的程序。唯一冷构建来自功能预检:编译/核验 **3.4154 s**,构建键 `bcb85b5dce729fe9b7a503919b720be03950ff31839877edd344377d4ee9cfc0` 与后续完整八路分阶段组相同;预检将运行终点设为 0.02 s,只改变运行时选项,未改变编译出的系统程序。这个单次冷编译时间可供首次运行成本参考,但本轮没有测得完整 0~10 s 的冷启动网页总时间,不把预检总时间冒用为正式结果。
## 浏览器内部、持久化和导出细分
分阶段组保留了原始 `fetch`、流读取、解码、JSON.parse、IndexedDB 事务和下载锚点的时间戳,没有克隆响应或重复解析。
| 观察区间 | 中位数 / s | 含义与边界 |
|---|---:|---|
| 点击运行 → 调用 fetch | 0.0234 | 含前端模型检查、快照/XML 和提交准备,未单独计 XML CPU |
| fetch → 收到响应头 | 0.0298 | 收到流式响应头,不表示仿真已经算完 |
| 响应头 → 读到流 EOF | 9.6765 | 包含后台计算、传输、消费者处理与调度 |
| 累计未完成的流 read 等待 | 9.4636 | 含后台结果尚未生成的等待,不能称为纯网络时间 |
| 最终结果的原始 JSON.parse | 0.1125 | 同步解析仅执行一次 |
| 全部流消息 JSON.parse | 0.1139 | 已含上一行 |
| UTF-8 decode 累计 | 0.0280 | 原始解码调用,不包含分片扫描/拼接 |
| 最终 JSON.parse 结束 → 完成 DOM | 0.0430 | 含应用处理和 React 调度,未独立测 React CPU |
| 结果解析结束 → IndexedDB 完成指针发布 | 2.6279 | 含批处理、事务等待与调度,可与看图重叠 |
| 首次保存事务 → 完成指针发布 | 2.5952 | 仍是异步区间;不是磁盘或主线程独占时间 |
| CSV 点击 → fetch | 0.2641 | 包含将整份结果再次 JSON.stringify 的提交准备 |
| CSV fetch → 响应头 | 4.6968 | 含浏览器请求准备、后台处理及网络/调度 |
| CSV 点击 → Blob 下载锚点 | 5.0143 | 浏览器已经取得并准备好下载数据 |
| 结果文件点击 → Blob 下载锚点 | 0.6113 | 包含结果文件序列化及 Blob 准备 |
最终流式响应约 **33.73 MB**;原生结果 JSON 为 32,725,293 字节,CSV 为 32,346,795 字节,结果文件约 33.85 MB(十进制 MB)。本次是本机回环 HTTP,未模拟远端带宽、TLS 或网络延迟;不能把这些网络相关耗时直接推广到远端部署。
CSV 后台另有独立请求,按请求顺序和时间戳关联,正式三次分段如下:
| CSV 后台阶段 | 中位数(最小~最大)/ s |
|---|---:|
| ASGI 开始 → 收完请求体 | 0.0262(0.0247~0.0285) |
| 收完请求体 → CSV 函数开始 | 0.7072(0.7010~0.7138) |
| CSV 校验、逐单元格式化与文本组装 | 2.3684(2.3616~2.3885) |
| CSV 函数结束 → HTTP 完成 | 0.1252(0.1221~0.1264) |
| CSV HTTP 全程(父区间) | 3.2264(3.2177~3.2494) |
“收完请求体→CSV 函数”约 0.707 s,涵盖路由层 JSON 解码、模型校验及调度,未再将每项 CPU 时间拆开。CSV 浏览器 fetch 到响应头比 ASGI 全程更长;跨进程请求准备、发送及调度的余量未进一步归因。CSV 的完整结果往返及文本组装成本已经实测,后续可据此单独优化。
## 本轮验证与下一步优先级
两组共 **8 次**网页运行均完成 10 s,且无 `pageerror`。每轮公开导出的工程参数与连接全部匹配固定输入;结果页、精确单位 K 的温度曲线、CSV、`.simresult` 下载和刷新恢复均通过。8 份 CSV 均为 1785 列 × 1002 数据行,合计 **14,308,560 个数值单元**与独立原生结果精确相等;全部 `series/final` 也精确相等,刷新前后完整结果一致。4 份后台稀疏插桩原生文件的 `series/final/finalState` 均与生产文件逐值相同。56 个唯一气体质量状态用 `math.fsum` 汇总,初始总质量 5.566893015 kg,最大漂移 **1.15463e-14 kg**;所有保存数值有限。
初次自动化预检曾误用旧控制台 CSS,另一次重复组在刷新后假定建模工程自动恢复而未提交新请求。这两类脚本失败保存在 `browser-stage-smoke/` 与 `browser-control-failed/`,明确排除正式统计。最终脚本使用当前 DockedSimulationConsole、每轮重新导入并核对工程,两个完整正式组均通过。0.02 s 的功能预检只证明操作流程,不混入八路完整计算效率。
依据本轮数据,后续优先考虑:
1. **先追踪八路早期压力/温度差和碰撞事件输出。** 参数对齐与局部求根成功不能代替整条曲线正确性;保留八路主案例,继续固定当前输入与精度。
2. **减少结果反复文本化。** 当前 C 写 JSON、Python 再解析、HTTP 再序列化合计约 2.95 s;优化这条路径时仍需保留全部变量、采样、浮点数值与输出合同。
3. **单独优化 CSV 与浏览器持久化。** CSV 全量回传后台并组装文本明显影响使用时间;持久化约 2 s 以上、且与查看曲线重叠,适合分别评估批大小、复制与调度,不能把保存等待计为绘图耗时。
4. **继续剖析 RHS/雅可比等求解成本。** 管流触顶已经为零,当前再削减迭代上限没有实测依据。可先评估本例零命中的管流缓存和 74265 次 RHS 的组成;更改雅可比或缓存策略后仍按同一八路、同精度和完整输出复核。
![八路算法与网页阶段耗时](assets/2026-09-11/mql8-efficiency-20260911-stage-costs.png)
图中三算法与浏览器操作取三次中位数;后台堆叠图选 HTTP 总耗时居中的单个请求,所有片段可相加。浏览器各操作区间不能相加;完整可缩放图为 [SVG](assets/2026-09-11/mql8-efficiency-20260911-stage-costs.svg)。
## 与当前 Amesim 归档的对照
本次找到可用的八路保存曲线。独立核对当前 AME 内的图纸、参数数据、编译 C、状态与变量索引及初值,未发现此前四路归档中那种图纸/缓存错配;完整说明见 [当前八路归档与曲线核查](test-mql-8当前AME归档与完整曲线核查-2026-09-11.md)。使用的是当前 AME SHA,未套用绑定另一归档的历史八路冻结基准。
选取全部 132 个连续状态对应的压力、温度、位移与速度,另加阀流量、接触力、限位力和间隙,共 **176 条曲线**;明确映射表压/绝压、SI 单位与接口方向,分别在双方原始保存网格上线性插值对照,不删去原生事件点。下表为 AME 保存网格上各类最差曲线的最大差及该曲线 RMS,不是把全类所有点混算的 RMS。
| 量 | 最大绝对差 | 对应曲线 RMS |
|---|---:|---:|
| 压力 | 163395.189 Pa | 7170.441 Pa |
| 温度 | 105.215279 K | 5.829065 K |
| 阀质量流量 | 0.002990901 kg/s | 0.000114014 kg/s |
| 接触力(AME 保存网格) | 5131.971 N | 225.218 N |
最大压力、温度和此表接触力差在 0.01 s,不能全归因于后续碰撞采样时刻不一致。原生另有 `t=0.9833956321732664 s` 的原始事件点,8 个接触力约 **4.035×10¹¹ N**;AME 只保存相邻 0.98 / 0.99 s 点,无法据其线性插值判断 Amesim 精确事件时刻或是否也有极窄峰。当前 AME 的 UD00 输入含 `1e17` 初始信号,双方公共质量元件都出现极大位移/速度,也不能把“数值有限”当成物理合理性证明。本轮未修改这些 AME 参数。
因此,**八路运行与计时记录完成,不等于八路曲线一致性验收通过**。目前没有八路专用接受阈值,也缺少足够密的 AME 事件输出;保留差异供后续核查,不为通过而放宽门槛或换四路。
Amesim **耗时对比跳过**:当前环境没有可调用的 Amesim,归档也没有可信 CPU/墙钟记录;`.ameperf` 中的时间是仿真事件时刻。归档名义容差为 `1e-7`,本轮为 `1e-8`,也不能冒称同精度速度比较。没有重跑 Amesim,没有从 10 s 仿真终点或文件时间戳推算耗时。
## 记录、脚本与复现
所有输入快照、编译程序、完整曲线、下载文件和浏览器截图都放在 Git 忽略目录 `test/`,环境仍在 `.venv/native/`,未纳入 Git。报告引用的相对路径在仓库本地可打开;这些大型运行产物不随 Git 克隆传递。
- [三算法原始基准](../../test/mql8-efficiency-20260911/native-benchmark/summary.json)、[三算法汇总](../../test/mql8-efficiency-20260911/native-summary.json)、[正式构建独立基准](../../test/mql8-efficiency-20260911/native-production/summary.json)。
- [完整管阻计数与同输入重放](../../test/solver-newton-20260911/pipe-iteration-profile-8/summary.json)、[插桩与生产逐值核对](../../test/solver-newton-20260911/pipe-iteration-profile-8/production-parity.json)。
- [阶段汇总 JSON](../../test/mql8-efficiency-20260911/stage-summary.json)、[阶段汇总 CSV](../../test/mql8-efficiency-20260911/stage-summary.csv)、[网页对照组](../../test/mql8-efficiency-20260911/browser-control/summary.json)、[网页分阶段组](../../test/mql8-efficiency-20260911/browser-profiled/summary.json)。
- [网页与 CSV 全量相等核查](../../test/mql8-efficiency-20260911/equality.json)、[后台插桩逐值核查](../../test/mql8-efficiency-20260911/backend-profile-production-parity.json)、[质量守恒](../../test/mql8-efficiency-20260911/mass-conservation.json);每个后台请求在 `test/mql8-efficiency-20260911/backend-profile/requests/<simulationId>/` 保存执行 XML、原生 JSON、日志和阶段时间。
- [后台分阶段诊断脚本](../../tests/manual/backend_stage_profile.py)、[真实浏览器计时脚本](../../tests/manual/browser_stage_profile.mjs)、[管阻计数脚本](../../tests/manual/profile_pipe_iterations.py)。[网页结果复核脚本](../../tests/manual/compare_browser_stage_outputs.py)。这些都是手动诊断入口,生产服务无需加载。
```bash
# 八路三算法基准;目录必须为新目录
.venv/bin/python tests/manual/benchmark_native_pipe_solver.py \
tests/data/test-mql-8-corrected.json --output-dir test/new-mql8-variants --runs 3
# 正式构建独立基准
.venv/bin/python -m app.simulation.native_codegen tests/data/test-mql-8-corrected.json \
--output-dir test/new-mql8-production --runs 3 --timeout 120
# 后台阶段记录服务;需要已有 frontend/dist,选空闲端口
.venv/bin/python tests/manual/backend_stage_profile.py \
--output-dir test/new-mql8-backend --port 8012
# 另一个终端:--plain 为无诊断插桩的对照服务
.venv/bin/python tests/manual/backend_stage_profile.py --plain \
--output-dir test/new-mql8-control --port 8013 \
--frontend-dist test/new-mql8-backend/frontend
# Chromium 所需依赖仅使用仓库现有忽略环境
export LD_LIBRARY_PATH="$PWD/.venv/native/browser-libs/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
.tools/node-v24.18.0-linux-x64/bin/node tests/manual/browser_stage_profile.mjs \
--output test/new-mql8-browser-control --url http://127.0.0.1:8013 --mode control --runs 3
.tools/node-v24.18.0-linux-x64/bin/node tests/manual/browser_stage_profile.mjs \
--output test/new-mql8-browser-profiled --url http://127.0.0.1:8012 --mode profiled --runs 3
```
@@ -0,0 +1,158 @@
# 八路结果处理、浏览器保存与 CSV 优化(2026-09-11)
本轮针对“点击运行→结果可查看”“点击运行→浏览器保存完成”“CSV 下载保存”三个用户关注的时间点实施优化。基线为 `808c484`,主案例仍是 [修正后的八路工程](../../tests/data/test-mql-8-corrected.json),未退回四路。此前各阶段成本见 [八路评估报告](八路模型计算效率与网页阶段计时-2026-09-11.md)。
## 实现
### C 数值 JSON 直接进入 HTTP 结果流
C 继续生成原有 `result.json`,数值仍使用 `%.17g`,新增可选 `--result-index` 小索引文件。索引通过写文件时的实际字节位置标出完整 `series` 对象,包含版本、边界、文件长度和采样数;主结果成功关闭后才发布索引,定位或文件写入失败返回错误。
网页流式请求启用原生片段传输:Python 校验索引版本、整数边界、文件长度与布局,只解析较小的诊断和最终值;采样数组保留为 C 已生成的 JSON 字节。返回时标准 JSON 编码器处理模型元数据、名称、单位和诊断,原始数值片段直接放入 `result.series`,不再次转换为 Python 浮点数组或重新编码这些数组。浏览器仍收到原有 JSON 对象和普通数字数组,没有改成二进制接口。
字节内容在临时工作目录删除前已经独立持有,任务保留及重复 GET 查询也可直接返回。默认 Python 调用、同步 HTTP 仿真与独立 CLI 仍提供普通结果对象;取消、失败和部分结果的状态规则保持原合同。原始片段仅来自受控 C 输出,用户模型文字继续经过标准 JSON 转义,不按字符串搜索猜测边界。
C 的 JSON 数字格式化成本仍存在;本轮着重省去大数组在 Python 中的解析和再次编码。方程、牛顿/二分算法、积分器、误差限、事件点与采样没有修改。
### 浏览器打包保存与旧缓存兼容
原保存方式按每个输出列写独立块,八路一次结果有 1785 个数据写入、14 个顺序事务。新方式把短列连成固定容量的 Float64 数据块:完整八路约 7 块,每块最多 2 MiB,加 1 条头记录,在单次原子事务内提交;只有成功提交且仍是最新保存请求时,才更新小型 sessionStorage 指针。
复制过程分批让出主线程;换结果会停止旧保存,失败不发布新指针,只清理本页拥有的缓存。新记录带 `packed-f64-v1` 标记,读取通过少量 `getAll` 结果恢复;旧 IndexedDB 按列格式及旧 sessionStorage 格式继续可读。记录缺块、重叠、错误长度或未知布局会明确失败,不返回残缺结果。
### CSV 改在工作线程中生成
网页不再把全部曲线 JSON 回传给后台 CSV 接口。主线程按最多 1 MiB 的 Float64 数据批次转移给专用 Worker,Worker 按列序生成 CSV Blob;主线程保持可响应,重复点击、切换结果和组件卸载均有任务清理。保留原下载按钮和文件名规则,旧 HTTP CSV 接口仍可单独使用。
保留 time 首列、变量元数据顺序、原始单位、全部原始采样、UTF-8 BOM、CRLF 与 CSV 转义。数字使用可精确回读的最短十进制并保留负零;例如整数可能省掉 `.0`,所以 CSV 文本及文件 SHA 会变化,数值必须逐单元精确一致。未降低精度、删列或抽样来缩短用时。
## 验证条件
- 输入 SHA256:`670977bef67e62d9c66e8af497bada208bd72a7301be45128d185d47282cf288`;157 元件、178 条连接、132 状态、1784 输出变量。
- 八路 0~10 s、输出间隔 0.01 s,1002 个原始采样(含事件点);CVODE BDF / SUNDIALS 7.4.0,`rtol=1e-8`、`max_step=1e30`,状态绝对误差限保持质量1e-14、内能1e-8、速度/位移1e-12(各自SI单位)。
- 同一 Linux Xeon Silver 4210R 虚拟机、GCC 13.3.0、现有 Python .venv,正式网页使用 Node 24.18.0 构建和 Chromium 151.0.7922.34;未安装新环境或新增生产依赖。
- 旧版后台从 Git `808c484` 导出 app/native/schemas 到隔离目录,前端使用上一轮保存的同提交正式资产;优化版使用本轮源码。两者都是真实服务,不注入结果或模拟网络。
- 依次运行旧版无插桩、优化版无插桩、优化版分阶段诊断三组;每组预热一次、正式三次。正式计时期间没有安排并行求解、大编译或大文件比对;输出比较留到计时结束。
- 每轮先公开导入、导出并核对相同工程,再计点击运行时间;接着进入结果页、选择温度、CSV 和结果文件下载、刷新恢复。浏览器保存完成采用同一个 session 指针提交观察点,允许保存与查看自然重叠。
## 同机重新测得的前后用时
下表均取**无插桩组**预热后三次正式运行的中位数,括号为最小~最大值,单位秒。结果可查看以完成状态 DOM 和运行按钮恢复可用为准,另列两帧后的首次绘制机会以便对应此前报告。保存完成由相同 sessionStorage 指针观察,轮询间隔16 ms并含调度延迟;不是提前显示的保存提示。
| 指标 | 旧版 / s | 优化后 / s | 中位耗时降低 |
|---|---:|---:|---:|
| 点击运行 → 结果可查看(完成 DOM) | 9.8720(9.8700~9.9832) | 8.0341(7.9848~8.0377) | 18.62% |
| 点击运行 → 完成状态首次绘制机会 | 9.8931(9.8904~10.0018) | 8.0547(8.0017~8.0595) | 18.58% |
| 点击运行 → 浏览器保存完成观察 | 11.7740(11.6157~12.6169) | 8.1320(8.0843~8.1468) | 30.93% |
| CSV 点击 → 下载保存 | 5.6103(5.4994~5.7601) | 1.0051(0.9394~1.0077) | 82.08% |
| 刷新 → 结果首次绘制机会 | 0.6095(0.5541~0.6375) | 0.3768(0.3525~0.3980) | 38.18% |
三个目标均有改善:结果可查看节省约 **1.84 s**,结果保存完成节省约 **3.64 s**,CSV 下载保存节省约 **4.61 s**。这些区间重叠,不能相加为一次仿真的节省量。与上轮历史数据略有差异时,以本轮重新运行的旧版对照为计算比例的依据。
| 其他观察 | 旧版中位 / s | 优化后中位 / s |
|---|---:|---:|
| 工程导入到首次绘制机会 | 0.2325 | 0.2445 |
| 进入结果页到首次绘制机会 | 0.1825 | 0.1874 |
| 选择温度到曲线首次绘制机会 | 0.0286 | 0.0288 |
| 结果文件下载保存 | 1.3575 | 1.0118 |
| 刷新到结果DOM | 0.4669 | 0.2496 |
| 结果就绪DOM到保存指针观察 | 1.9040 | 0.0995 |
两组 C 纯求解中位数分别为 **6.1083 / 6.1013 s**,进程全程分别为 **8.0204 / 7.4582 s**。每次仍是 RHS 74265、接受6974、拒绝454;本轮收益来自结果处理与保存,而不是改变求解精度或少算输出。结果文件下载不是本轮主要改动,有限样本的时间变化不单独宣称为该功能优化收益。
下载完成计时包含 Playwright 通知和 saveAs 的文件系统成本;首个 DOM 后的两帧只是绘制机会,未直接测 GPU。正式页面均经本机回环 HTTP 访问,没有模拟远端网络。分阶段组相比优化版无插桩组有几%波动,其纯求解也从约6.10 s变到约5.94 s;CSV下载完成还有自动化/磁盘调度波动,故加速比例严格来自上面的两组无插桩对照。
![八路三个目标用时的前后对照](assets/2026-09-11/postprocess-20260911-before-after.png)
可缩放版本:[SVG](assets/2026-09-11/postprocess-20260911-before-after.svg)。图的“result visible”为完成状态DOM,与主表第一行相同。
## 优化后的后台阶段
分阶段服务使用隔离的 C 主程序时钟和真实函数包装;数值内核逐字节相同。按每个 X-Simulation-Id 关联网页与后台,以下为正式三次的秒数(中位、范围)。
| 阶段 | 中位数(最小~最大)/ s |
|---|---:|
| XML 校验 | 0.0227(0.0219~0.0232) |
| 网络编译 | 0.0393(0.0372~0.0425) |
| C 代码生成 | 0.0557(0.0539~0.0934) |
| 构建缓存核验(均命中) | 0.0339(0.0327~0.0340) |
| C 纯积分 | 5.9407(5.9370~6.0256) |
| C 输出投影 | 0.0799(0.0774~0.0813) |
| C 原始 JSON 与索引写出 | 1.1643(1.1578~1.1762) |
| Python 原始结果文件读字节 | 0.0250(0.0107~0.0269) |
| Python 解析小索引与元数据 | 0.0012(0.0011~0.0015) |
| 索引读取与片段整理全程(含上两项) | 0.0472(0.0350~0.0486) |
| 响应接口元数据组装 | 0.0172(0.0168~0.0176) |
| 响应小元数据 JSON 序列化 | 0.0329(0.0328~0.0329) |
| 序列化后至 ASGI 最后响应完成 | 0.0747(0.0528~0.1222) |
| 后台 HTTP 全程(父区间) | 7.5315(7.5174~7.6975) |
旧版阶段诊断中,Python 完整结果 JSON 解析约0.551 s、HTTP结果序列化约1.193 s;新路径只解析小元数据约0.0012 s,序列化约0.0329 s。旧阶段分项来自上一轮诊断报告,不用于替代本轮端到端的同机重新比较。C格式化/写出仍约1.16 s,后续还有优化空间。
原生片段整理全程约0.0472 s,包含读文件、小JSON解析、校验和series字节持有;不能与其子项重复相加。C main全程约7.1957 s,Python原生执行包装约7.2336 s,worker全程约7.4409 s,也都是包含子阶段的父区间。诊断产物保留另约0.00055 s;服务器send、后台生产和浏览器等待可能重叠。
## 浏览器保存与 CSV 的实际细分
以下来自优化后的分阶段组,所有时间为观察区间,含相应异步等待与调度。
| 观察区间 | 中位数 / s |
|---|---:|
| 点击运行至调用fetch | 0.0187 |
| 最终结果 JSON.parse | 0.0982 |
| UTF-8 解码总计 | 0.0297 |
| 结果解析结束至保存提交指针发布 | 0.1186 |
| IndexedDB 单次事务窗口 | 0.0549 |
| 完成状态DOM至保存完成观察 | 0.0829 |
| CSV工作线程start发送至finish发送 | 0.0681 |
| CSV finish发送至完成消息接收 | 0.3889 |
| CSV点击至Blob下载锚点 | 0.4893 |
| 结果文件点击至Blob下载锚点 | 0.5905 |
实际八路三次保存均为 **1 个事务、约55 ms**;事务前还需要打包和调度,所以不能把55 ms当成从计算结束到保存完成的全部时间。浏览器仍在同一提交完成后发布恢复指针,没有通过放宽持久化完成标准来提速。
CSV三次均未发HTTP请求。按批传输约68 ms;finish发出到完成消息收到约389 ms,含剩余工作线程计算、启动/排队和消息传递,不冒称纯Worker CPU时间。点击至Blob准备好约489 ms,实际下载保存的主结论仍使用无插桩组约1.005 s。
新CSV为31,820,845字节,旧版32,346,795字节,减少约1.63%;主要收益是省去全量JSON往返和后台逐单元格式化,并将生成放在工作线程,不能仅归因于文件体积变小。CSV编码采用Float64精确回读方式,数值一致性单独验证。
## 正确性与回归
29 项后端相关回归通过,覆盖原生执行、默认同步接口、真实 ASGI 流式响应与重复任务 GET、用户/异常断线取消后的部分结果、心跳、索引损坏与截断文件、JSON 边界转义、独立 C 程序和旧 CSV HTTP 合同。后续补全严格索引版本及 I/O 异常处理后,6 项传输专项再次通过。
6 项真实 IndexedDB 专项通过,覆盖完整八路形状的值、负零、空列、旧缓存、缺块/重叠、头记录写入失败、保存竞态和跨页面隔离。6 项 CSV 专项通过,包括 1052929 个值的精确回读、最小子正规数、极大数、负零、列顺序和转义、无 CSV HTTP 请求、重复点击与错误重试。专项合成数据耗时只用于功能诊断,不充当正式八路测量。正式 TypeScript/Vite 构建通过。
本轮发现已有 `tests/test_native_codegen.py` 引用的 `tests/fixtures/native-skill-test.xml` 在当前提交缺失,从 `5d5a2e1:tests/data/native-skill-test.xml` 原样恢复到其现行测试路径,保证相关回归可运行。没有放回浏览器输入目录或改变这份测试资料的物理内容。
三组共 **12 次**真实八路运行全部完成10 s,无页面错误。每次公开导出工程都与固定输入的全部参数、连接与设置一致;全部 `series`、`final` 与优化前原生基准精确相等。12份CSV合计 **21,462,840 个数值单元**与基准精确相等,各组内部CSV字节稳定;旧新文本差异符合前述编码规则。12次刷新前后的完整结果一致。
另外,4份分阶段组C原始结果文件的 `series/final/finalState` 均与旧原生基准逐值相同,证明后处理改动没有改变积分轨迹或事件点。这里只比较数值,不要求运行耗时等诊断字段在不同运行间相同。证据:[全量网页/CSV核对](../../test/postprocess-20260911/equality.json)、[C原始状态核对](../../test/postprocess-20260911/native-parity.json)。
## Amesim 范围
本轮处理优化不改变计算结果,沿用 [当前八路 AME 归档核查](test-mql-8当前AME归档与完整曲线核查-2026-09-11.md) 的差异记录。完整数值逐值不变后,原有早期压力/温度差及约0.9834 s碰撞力尖峰也会保留;不能把后处理提速解释为八路物理曲线验收通过。
当前没有可信 Amesim CPU/墙钟记录,也没有可调用的 Amesim 安装,速度对比仍跳过。后续继续使用修正八路,在相同输入、精度与完整采样下核查正确性与用时。
## 文件与复现
代码入口为 [原生片段传输](../../app/simulation/native_codegen/transport.py)、[C 结果索引](../../native/runtime/main.c)、[浏览器保存](../../frontend/src/resultPersistence.ts)、[CSV 导出任务](../../frontend/src/resultCsvExport.ts) 和 [CSV Worker](../../frontend/src/resultCsv.worker.ts)。
输入快照、隔离旧版、构建、运行结果和截图位于 `test/postprocess-20260911/`;环境仍在 `.venv/native/`。这些大型运行产物和环境均在 Git 忽略范围,本轮未提交或推送 Git。
- [三组逐次与汇总JSON](../../test/postprocess-20260911/summary.json)、[各阶段CSV](../../test/postprocess-20260911/timings.csv)
- [旧版网页记录](../../test/postprocess-20260911/browser-baseline/summary.json)、[优化版网页记录](../../test/postprocess-20260911/browser-optimized/summary.json)、[优化版分阶段记录](../../test/postprocess-20260911/browser-profiled/summary.json);每次截图、输入、结果与刷新文件保存在对应组子目录,后台逐请求阶段位于 `backend-profiled/requests/<simulationId>/stages.json`。
- [源码与输入清单](../../test/postprocess-20260911/source-manifest.json)
- [后端回归](../../test/postprocess-20260911/backend-tests.log)、[传输专项复测](../../test/postprocess-20260911/backend-transport-final.log)、[正式前端构建](../../test/postprocess-20260911/frontend-build.log)
- 计时脚本 [backend_stage_profile.py](../../tests/manual/backend_stage_profile.py)、[browser_stage_profile.mjs](../../tests/manual/browser_stage_profile.mjs);数值复核 [compare_browser_stage_outputs.py](../../tests/manual/compare_browser_stage_outputs.py)。
```bash
# 后端相关回归
.venv/bin/python -m unittest tests.test_native_result_transport tests.test_native_codegen \
tests.test_generic_system_xml_simulation tests.test_result_csv_export tests.test_native_only_backend -v
# 当前正式网页的独立服务与计时:两个终端分别运行,输出目录必须为新目录
.venv/bin/python tests/manual/backend_stage_profile.py --plain \
--output-dir test/new-results-service --port 8021
LD_LIBRARY_PATH="$PWD/.venv/native/browser-libs/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" \
.tools/node-v24.18.0-linux-x64/bin/node tests/manual/browser_stage_profile.mjs \
--url http://127.0.0.1:8021 --mode control --runs 3 --output test/new-results-browser
```
@@ -0,0 +1,210 @@
# 八路网页求解全流程成本评估(2026-09-11)
本轮评估上一轮结果处理优化后的当前版本,目标是分清前端预处理、后端准备与计算、结果输出、浏览器后处理的成本。使用 [test-mql-8-corrected.json](../../tests/data/test-mql-8-corrected.json),没有修改生产算法、物理输入、积分精度或输出点数。此前实现与前后加速见 [结果处理优化报告](八路结果处理与网页保存优化-2026-09-11.md)。
**当前主要成本集中在后端数值积分和 C 结果写出。** 无插桩正式三次中位数:点击运行到结果可查看 **7.99 s**,到浏览器保存完成 **8.11 s**。分阶段组内逐次计算,积分占点击到可查看时间约 **76.4%**,C结果编码与写出占约 **14.8%**。前端点击后的预处理仅约 **19.6 ms**,不属于当前优先优化的大项。
## 测量条件与可复现证据
- 模型 SHA256 为 `670977bef67e62d9c66e8af497bada208bd72a7301be45128d185d47282cf288`;157 元件、178 条连接、132 状态,1784 输出变量和时间列,1002 个原始采样。
- 0~10 s,输出间隔0.01 s,CVODE BDF,`rtol=1e-8`、`max_step=1e30`,状态绝对误差下限保持原值;事件和采样策略均不变。
- Git 基线 `808c484` 加上一轮尚未提交的结果处理优化。所有上一轮生产源码清单中的文件哈希一致;本轮只增加/完善手动测量工具与报告。环境继续使用已有 `.venv`、`.venv/native`、Node24.18.0、Chromium151.0.7922.34;没有安装新依赖。
- 使用真实生产页面,经本机回环 HTTP 提交。每轮公开导入、导出并核对八路工程参数、连接和仿真配置,再点击运行,进入结果页显示温度曲线,保存 CSV 和结果文件,刷新恢复。
- 无插桩组、分阶段组各预热一次、正式三次;串行运行,计时期间不安排大型构建、其他仿真或全量文件比对。端到端体验以无插桩组为准。分阶段组用于定位成本,不把其耗时套入无插桩组拆账。
- 分阶段后台只在隔离的 C `main.c` 副本增加少量墙钟/CPU时钟,数值实现未改;Python 包装原函数,观察子进程创建、退出及实际读取/响应边界,不额外轮询。C写出 CPU 时钟包括用户态和内核态,不能单独区分格式化、内存访问与系统调用。
- 分阶段网页包装原有 fetch、reader、decoder、JSON.parse、IndexedDB 和 Worker 调用,保持每份响应仅读取、解码和解析一次。另有独立 CDP CPU 采样诊断,不混入正式端到端结果。
“结果可查看”指页面观察到成功完成且运行按钮恢复可用;“绘制机会”指再经过两次 requestAnimationFrame,不等于直接测得 GPU 绘制时间。“浏览器保存完成”指实际 IndexedDB 事务提交后发布恢复指针;无插桩组通过16 ms轮询观察,含调度延迟。“下载保存完成”包括 Playwright 通知及 `saveAs` 的文件系统成本。
## 网页端到端体验
下表为无插桩组预热后三次中位数及范围,单位秒。导入工程发生在点击运行之前,不计入仿真总耗时。
| 用户过程 | 中位数(最小~最大)/ s |
|---|---:|
| 点击运行 → 结果可查看 | 7.992(7.927~8.104) |
| 点击运行 → 完成状态绘制机会 | 8.015(7.944~8.122) |
| 点击运行 → 浏览器保存完成观察 | 8.108(8.043~8.218) |
| CSV点击 → 下载保存完成 | 0.912(0.884~0.984) |
| 结果页签点击 → 绘制机会 | 0.193(0.181~0.240) |
| 温度变量点击 → 曲线绘制机会 | 0.029(0.028~0.029) |
| 刷新 → 结果绘制机会 | 0.437(0.427~0.452) |
| 结果文件点击 → 下载保存完成 | 1.154(1.033~1.223) |
工程导入到绘制机会为 0.238(0.231~0.247) s。三次完整运行的 C 纯求解中位数为 6.143 s;每次均完成10 s物理区间。
首次打开无插桩页面至自动化确认导入控件已附加约0.530 s,属于一次独立导航观察,含自动化确认延迟;不等同首帧或完整应用就绪时间,未计入上面的点击运行用时。
## 前端预处理、接收与后处理
分阶段组三次正式运行;所有值为毫秒。各行可能重叠。
| 过程 | 中位数(最小~最大)/ ms | 口径 |
|---|---:|---|
| 点击→提交fetch:校验、快照、XML和请求准备 | 19.6(18.8~31.9) | 毫秒;同步预处理与提交设置的整体窗口 |
| fetch→响应头可供读取 | 29.9(28.7~30.0) | 毫秒;包括请求处理、传输和浏览器调度 |
| 流UTF-8解码同步调用之和 | 32.2(30.8~33.0) | 毫秒;与接收过程重叠 |
| 最终结果JSON.parse | 107.0(105.5~119.6) | 毫秒;原始单次同步解析 |
| 解析结束→完成DOM | 48.2(42.4~58.2) | 毫秒;发布状态、渲染准备与调度 |
| 进入结果页→绘制机会 | 182.0(181.1~196.7) | 毫秒;包含系统图准备 |
| 温度曲线选择→绘制机会 | 35.7(34.4~36.3) | 毫秒;单条温度曲线 |
| 最后分块交付→开始解析 | 36.6(33.3~45.3) | 含最后一次解码、扫描、拼接、trim及调度,不能全归于join |
| 解析结束→缓存指针发布 | 135.5(127.0~176.5) | 包含数据打包、让出主线程、数据库打开/提交、页面工作 |
| 保存事务窗口(每次1次) | 63.1(50.0~84.5) | 包含同步提交及异步等待,是上一行子区间 |
从最后一次分块交付到完成DOM为 197.0(191.8~207.3) ms;这比整段 headers→EOF 更接近最终结果到达后的页面处理窗口。后者约 7.866 s,绝大部分与后台执行同时发生,不能称为前端解析用时。
CSV 点击到 Blob 下载触发为 494.9(487.4~495.9) ms;Worker start→finish投递为 77.3(69.1~86.2) ms,finish投递→完成消息到达为 382.9(377.8~386.7) ms。前一段主线程分批准备与Worker执行重叠,后一段包含Worker编码/Blob生成/消息投递和调度。没有单独测量Worker线程CPU。CSV完整下载体验仍以无插桩组为准。
### 主线程 CPU 采样补充
另对真实页面做1 ms间隔的CDP主线程采样,预热一次、正式三次。使用临时生成的hidden source map映射回源码;临时构建的JS与实际服务的生产JS逐字节一致,未替换页面资产。采样组点击→可查看中位8.152 s,独立于上面的无插桩/分阶段组。下表为采样归属估计,精度受约1 ms采样与时钟校准误差限制,不能当作逐函数秒表。
| 观察窗口 | 可识别的主要工作,采样归属中位 / ms |
|---|---|
| 点击→fetch(该诊断组27.1 ms) | 模型校验15.0;XML构造7.8;XML原生序列化2.3;项目快照1.2;端点/合同处理1.1 |
| 响应头→大结果开始解析 | NDJSON扫描/拼接/分发40.2;UTF-8解码29.2;React更新69.3;其余含进度显示和测量工作 |
| 大结果解析开始→保存指针(255.3 ms) | JSON解析归属103.5;IndexedDB请求提交62.2;打包/保存逻辑11.3;React7.9;GC12.7 |
| 进入结果页→绘制机会(207.6 ms) | React运行时77.7;ReactFlow系统图52.6;结果视图数据准备9.3;系统图几何处理5.9 |
| 选择温度→曲线绘制机会(28.4 ms) | 结果视图8.0;React7.1;曲线数据准备2.6 |
| CSV点击→文件保存 | 主线程分批准备和传输36.6;其余可识别主线程工作包括视图与React;不含Worker线程CPU |
IndexedDB“请求提交”类别包含相应JS调用下的原生同步处理,不代表后台磁盘线程耗时。CPU样本中的JSON解析归属与同步wrapper实测是两种观察,不能相加;其余分类和不同窗口也不能直接相加成总耗时。
响应头到最终结果解析前约7.947 s的窗口,采样明确空闲约5.592 s,V8 `(program)` 未归属约2.086 s,可识别JS及其下原生调用约0.265 s。其中仍有约0.127 s未归到具体业务函数,含DOM观测/自动化;**不能把2.086 s未知时间或整段7.947 s计作前端业务CPU**。GC、idle、program、unknown-runtime单列,函数active统计排除这些样本。
结果页准备比单条温度曲线的数据准备更显著;采样主要落在React/ReactFlow与DOM操作,不足以将其直接称为GPU绘制耗时。刷新恢复另有独立profile,使用刷新后的document时间轴。
采用离线修订的v2分类,不使用会混淆系统样本的初始汇总字段。证据:[cpu-resummary-v2.json](../../test/web-cost-20260911/browser-deep/cpu-resummary-v2.json)、[frontend-cpu-statistics.json](../../test/web-cost-20260911/frontend-cpu-statistics.json)、[sourcemap-verification.json](../../test/web-cost-20260911/sourcemap-verification.json)。原始 `.cpuprofile`、`trace.json` 与网页计时结果均保持原样。
## 后端准备、求解、输出与响应
分阶段组三次正式运行;单位秒。包含“其中”的行是父区间子项,不应重复累计。
| 阶段 | 中位数(最小~最大)/ s |
|---|---:|
| XML校验 | 0.0225(0.0220~0.0236) |
| 网络编译:组件和连接 | 0.0372(0.0365~0.0454) |
| C模型代码生成 | 0.0601(0.0540~0.0863) |
| 构建缓存校验(命中) | 0.0349(0.0341~0.0417) |
| 子进程创建Popen调用 | 0.0006(0.0006~0.0007) |
| C初始状态和首样本准备 | 0.0001(0.0001~0.0001) |
| C数值积分,含求解器内部工作 | 6.0645(6.0614~6.1547) |
| 输出投影:由状态计算全部输出 | 0.0852(0.0852~0.0861) |
| C结果JSON及索引格式化/写出 | 1.1752(1.1620~1.1862) |
| Python结果索引读取、校验和片段整理 | 0.0440(0.0334~0.0466) |
| 其中:原始结果文件读字节 | 0.0230(0.0112~0.0254) |
| 其中:小索引和元数据JSON解析 | 0.0012(0.0011~0.0015) |
| 响应元数据组装 | 0.0164(0.0164~0.0175) |
| 响应包装:元数据编码与字节片段组织 | 0.0354(0.0340~0.0357) |
| ASGI send累计await | 0.0794(0.0396~0.0845) |
| 后台HTTP总窗口(父区间) | 7.6916(7.6678~7.7199) |
XML校验、网络编译、C代码生成、缓存检查的同次合计为 0.1630(0.1565~0.1789) s。C初始状态准备只包含 `model_init` 和首样本,CVODE对象创建、初始化和重启仍属于积分区间。
C输出投影CPU为 0.0852(0.0851~0.0860) s;JSON写出CPU为 **1.1749(1.1619~1.1859) s**,与墙钟 1.1752 s 几乎一致。这支持优先调查数值格式化、逐值stdio调用和内存访问;不能将整段1.18 s称为磁盘等待,也不能把CPU/墙钟差直接当成测得的I/O耗时。
响应数值原始片段约32.64 MB,整条HTTP响应约34.48 MB,CSV约31.82 MB(十进制MB)。当前后端已避免Python大数组解析/重编码,但C逐值 `fprintf("%s%.17g", …)` 的成本仍保留。
`processWallSeconds` 包括退出后的Python结果读取;本轮另记录子进程从创建到已有poll/wait首次观察到退出的寿命,不能混称C求解时间。ASGI send窗口也不是纯网络耗时;本机回环测试不代表远端网络。
**首次编译单独记录:** 分阶段组首轮缓存未命中,构建耗时 **3.446 s**,点击到可查看 **11.447 s**。这是一次冷构建观察,不纳入三次缓存命中的正式中位数,也不当成稳定冷启动统计。修改会影响生成代码的模型内容后,可能重新发生该成本。
### 积分内部的计算分布
另做独立原生诊断:复用真正生产缓存可执行文件作control,隔离副本只在调用边界增加嵌套时钟并读取CVODE计数。每个变体预热一次、正式三次,交替串行运行;不是在网页中再开第二个求解任务。
表中为**排他墙钟时间**,同一次运行中已扣除子调用;每次所有排他区间之和精确等于积分父区间。中位数列来自三次运行,不再相加假装某次总耗时。
| 积分内部工作 | 排他时间中位 / s | 同次积分占比的中位数 |
|---|---:|---:|
| 模型RHS:物性、管流局部求根及组件方程等全部模型求值 | 5.559250 | 93.7191% |
| Dense矩阵分解 | 0.180638 | 3.0452% |
| Dense线性方程回代求解 | 0.110131 | 1.8620% |
| CVODE剩余内部工作(已扣RHS、poll、Dense) | 0.069325 | 1.1660% |
| 超时/取消/进度轮询 | 0.007586 | 0.1279% |
| 积分外层准备、循环和清理余量 | 0.001608 | 0.0272% |
| 接受步与事件处理自身(已扣采样和插值) | 0.001412 | 0.0237% |
| 保存采样状态 | 0.000806 | 0.0136% |
| 稠密输出插值 | 0.000293 | 0.0049% |
诊断积分中位 **5.931924 s**,配对生产control为 **5.874992 s**;逐对计算的插桩增幅中位约 **0.91%**(0.68%~1.71%)。原始summary的 `instrumentationOverheadFraction` 采用两组中位数之比,估计为0.97%;两者计算口径不同。此处为独立进程诊断,其绝对耗时不直接替代网页组的6.06 s;用作积分内部占比定位。时钟/统计维护成本仍在诊断结果中。
**关键发现是雅可比所需的方程求值次数。** 每次实际读取CVODE统计均为:
| 计数 | 实测值 |
|---|---:|
| 常规RHS求值 | 11,565 |
| 线性求解器有限差分RHS求值 | 62,700 |
| 合计模型RHS | 74,265 |
| 雅可比计算次数 × 状态数 | 475 × 132 = 62,700 |
| 非线性迭代 / 非线性收敛失败 | 11,557 / 414 |
| Dense分解 / 线性回代调用 | 1,656 / 11,557 |
| 分段计数 / 求解器启动 | 4 / 4 |
有限差分占全部RHS**调用次数的84.43%**。结合全部RHS耗时占积分的93.72%,应优先研究如何减少重复模型求值。没有单独计时“差分RHS子集”,不能据此声称差分恰好占84.43%的积分时间,更不能承诺减少同等比例的总耗时。Dense代数自身合计约4.91%,单独更换矩阵分解实现的潜在收益较受限;雅可比结构改变带来的RHS次数减少属于另一项收益。
414是CVODE本级非线性收敛失败计数,后续通过重试完成仿真,不是管路局部Newton达到上限的次数。本轮未继续拆分RHS中的物性、管路求根和组件方程,不能将5.56 s全部归给管路求根。
所有8次原生运行的完整series、final、finalState和求解计数(只排除两个solve计时字段)与生产control精确一致。工具和原始证据:[native_compute_profile.py](../../tests/manual/native_compute_profile.py)、[native-compute-profile/summary.json](../../test/web-cost-20260911/native-compute-profile/summary.json)。
## 下一步优化顺序
1. **计算核心:验证减少雅可比差分所需RHS求值。** 研究生成模型的状态依赖结构、可复用的导数和稀疏差分/着色方案;保持当前精度、事件与物理参数,单独验证全曲线和守恒。这是本轮看到的最大计算成本来源,但尚未实现或证明某种替代方案的收益。
2. **结果处理:优先优化C数值编码与写出。** 当前仍约1.18 s,明显大于Python读回和网页JSON解析。可比较更高效且精确回读的数值编码、批量输出,或直接数值缓冲传输;需保留原始采样和数值精度。本轮没有改变传输合同。
3. **前端后处理:针对结果解析和缓存提交做小幅改进。** JSON.parse约0.11 s,数据打包/IDB提交约0.1 s量级;若优先改善主线程响应,可研究转移解析、减少数组复制。预期端到端空间小于上面两项,收益需实测。
4. **模型编辑后的首次运行:单独调查构建缓存。** 本轮冷构建一次约3.45 s;若用户经常改参数/拓扑导致缓存失效,应单独分析编译单元复用和参数是否必须进入生成代码,不能只看缓存命中数据。
5. **前端预处理和小项暂缓。** 点击后的整体准备约20 ms;Python元数据解析约1 ms、进程启动不足1 ms、事件采样/轮询均很小,当前不适合优先投入。
![当前八路模型的阶段成本](assets/2026-09-11/web-cost-20260911-cost-breakdown.png)
可缩放图:[cost-breakdown.svg](assets/2026-09-11/web-cost-20260911-cost-breakdown.svg)。三个面板分别使用后端网页组、独立原生诊断组和前端网页组;前端各行存在重叠,不能相加。
## 数据完整性与边界
三组共 **12 次网页运行**全部成功,无页面错误;完整曲线、最终输出及 **21,462,840 个CSV数值单元**均与既有C原生结果逐值精确相等,刷新恢复一致。每次 `nfev=74265`、接受步6974、错误测试失败454、Jacobian计数475、线性求解准备1656、状态跳变1、求解器启动4,均与原模型一致。数值比较不含本来就变化的计时诊断。证据见 [equality.json](../../test/web-cost-20260911/equality.json)。CSV文本SHA本轮各组也相同。
本轮没有可调用的 Amesim 运行环境及同工况可靠墙钟/CPU耗时,因此不作 Amesim 速度比较;此前已记录的 Amesim 曲线差异结论保持原状。本报告是当前网页路径的性能评估,不新增曲线一致性验收结论。
前端等待与后端执行同时发生,C积分内又包含RHS、雅可比和线性求解;后台响应发送与前端接收/解码也可重叠。表中父子区间及不同线程区间不能直接相加。独立阶段中位数的和也未必等于总耗时中位数。占比需在同一次运行、同一父区间内先计算,再汇总。
## 文件位置
- 本报告:[八路网页求解全流程成本评估-2026-09-11.md](八路网页求解全流程成本评估-2026-09-11.md)。
- 全部原始产物:[test/web-cost-20260911/](../../test/web-cost-20260911/),此目录被 Git 忽略。
- 无插桩网页记录:[browser-control/summary.json](../../test/web-cost-20260911/browser-control/summary.json)。
- 分阶段网页记录:[browser-profiled/summary.json](../../test/web-cost-20260911/browser-profiled/summary.json);各轮目录有 `trace.json`、`restore-trace.json`、结果、CSV与截图。
- 后端记录:[backend-profiled/requests/](../../test/web-cost-20260911/backend-profiled/requests/),以网页记录的 `simulationId` 关联;每项有真实输入XML、C原始结果、worker日志和 `stages.json`。
- 汇总:[summary.json](../../test/web-cost-20260911/summary.json)、[timings.csv](../../test/web-cost-20260911/timings.csv);源码与环境:[source-manifest.json](../../test/web-cost-20260911/source-manifest.json)。
- 手动工具:[backend_stage_profile.py](../../tests/manual/backend_stage_profile.py)、[browser_stage_profile.mjs](../../tests/manual/browser_stage_profile.mjs)、[summarize_web_cost.py](../../tests/manual/summarize_web_cost.py)。
以下命令使用新的输出目录复现;已有输出目录保留原始记录,不覆盖。后台服务需各自保持运行,网页各组与原生诊断串行执行。
```bash
# 无插桩服务 / 后台分阶段服务(分别运行)
.venv/bin/python tests/manual/backend_stage_profile.py --plain --port 8024 --output-dir test/web-cost-repeat/backend-control
.venv/bin/python tests/manual/backend_stage_profile.py --port 8023 --output-dir test/web-cost-repeat/backend-profiled
# 网页组:先control,然后profiled;各预热1次、正式3次
export LD_LIBRARY_PATH="$PWD/.venv/native/browser-libs/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
.tools/node-v24.18.0-linux-x64/bin/node tests/manual/browser_stage_profile.mjs --url http://127.0.0.1:8024 --output test/web-cost-repeat/browser-control --mode control --runs 3
.tools/node-v24.18.0-linux-x64/bin/node tests/manual/browser_stage_profile.mjs --url http://127.0.0.1:8023 --output test/web-cost-repeat/browser-profiled --mode profiled --runs 3
.venv/bin/python tests/manual/summarize_web_cost.py --root test/web-cost-repeat
```
深度采样增加 `--deep --cpu-interval-us 1000 --source-map-dir PATH`,使用独立输出目录;source map的生成JS须与生产资产哈希相同。只重新分类现有数据可执行:
```bash
.tools/node-v24.18.0-linux-x64/bin/node tests/manual/browser_stage_profile.mjs --summarize-cpu-only test/web-cost-20260911/browser-deep --source-map-dir test/web-cost-20260911/frontend-sourcemaps/assets
```
原生内部诊断使用生产模型缓存和已记录的请求参数;本轮命令:
```bash
.venv/bin/python tests/manual/native_compute_profile.py \
--cache-dir app/data/native-builds/00a1cc841fb4496044c99e13066bbd18784aef134893c3c30b5b984c7aef8eec \
--request-stages test/web-cost-20260911/backend-profiled/requests/e18c2e0e-b2e7-4219-9f5a-c09a26cde4fa/stages.json \
--output-dir test/native-cost-repeat --run --warmups 1 --repeats 3
```
原生工具目前针对Linux/GCC;所有新产物均位于已忽略的 `test/` 中。手动工具Python语法检查、Node语法检查、离线分类自检和汇总一致性检查通过;没有为本轮只读评估重新改动生产组件或降低精度。
@@ -0,0 +1,31 @@
# 优化验证的模型、数据和计时口径
本约定记录用户于 2026-09-11 明确的长期偏好,适用于后续仿真正确性检查与性能优化。
## 默认模型与退路
优先使用 `tests/data/test-mql-8-corrected.json`,Amesim 来源严格对应 `tests/data/test_mql.ame`。先核实当次文件与物理输入,不按显示名、目录名或历史报告标题认定为同一模型。原始旧工程仅保留审计用途,不重新作为活动输入。
只有八路模型确实跑不通,而且短期内没有可行修复时,才退回 `tests/data/test-mql-4-corrected.json` 与 `tests/data/test_mql_4.ame`。报告必须记录八路失败的实际终点、诊断、已排查内容及退回原因;四路结果不能代替八路验收。
## 先核对实际数据,再计时
逐元件、逐端口、逐参数检查拓扑和物理量,尤其是参考口、表压与绝对压力、SI 换算、力和流量方向、初始化及信号时刻。完整区间实际结果、守恒、事件和所需曲线按明确口径核查。存在数值差异时仍可按用户要求测量并记录运行成本,但必须将其标为性能观察,不能据此宣布正确性验收通过。完成运行和数值有限只证明可运行,不能直接判定曲线一致。
AME 文件是归档。必须记录外层 SHA-256,并核实 `.cir`、编译 `.c`、`.param`/`.data`、`.modelinfo`、`.var`/`.results`、`.sim` 的子模型、参数布局、变量索引、初值和时间范围相互对应。图纸与缓存不同就不能使用缓存作为当前参考。冻结基准绑定的另一个 AME SHA 不能因为文件同名就移作当前数据。
曲线对照保留原始采样点和事件点,明确变量映射、单位、方向、插值方法与范围。按量纲报告全时点最大绝对误差、均方根误差及定义清楚的相对误差,并单独说明事件时刻差异。峰值归一化误差不冒称为逐点相对误差;不能删去异常点、平滑尖峰或只选常规采样点来宣称整条曲线一致。缺少同工况数据或验收阈值时,明确标记该项 `skip` 或“仅观察,未验收”。
Amesim 速度比较需要同模型、同设置、完整区间的真实 CPU/墙钟记录。`.ameperf` 内的仿真事件时间不是运行耗时,归档成员修改时间也不能推导运行耗时。缺少可信耗时则明确 `skip` 速度比较;仍可独立报告满足来源条件的已保存曲线观察。
## 固定精度与运行条件
当前用户已批准网页/API 默认 `rtol = 1e-8`。同一性能比较中的精度必须固定,记录实际生效的 `rtol`、`atol`/状态误差下限、求解器、最大步长、输出间隔、起止时间、事件策略及雅可比策略。不能通过放宽精度、缩短区间、减少输出或改变物理参数制造加速结论。精度或模型变化后另建比较组,不能直接用旧组耗时计算优化比例。
正式计时记录源码版本、输入和原始结果 SHA、构建标识、编译器及积分库版本、硬件与运行环境。固定预热规则、缓存状态和重复次数,同机比较时避免并行求解、大编译等 CPU 干扰;报告逐次耗时及汇总口径。单次完整运行用于功能验证,不据此认定性能提升。
## 分阶段记录
分别记录输入加载/校验、代码生成、构建和缓存检查、进程启动、C 纯求解 CPU/墙钟、结果整理/序列化/传输,以及网页接收、持久化、曲线展示和导出。只测到总耗时就称为总耗时,不能把差值未经测量地归于某个阶段。
每次运行保存实际设置、成功或失败状态、实际终点、采样数量、求值次数、接受/拒绝步数、雅可比/线性分解次数、事件诊断和守恒结果。报告链接到原始产物,明确哪些阶段未测量、哪些比较因数据不足而跳过。后续优化以通过正确性检查后的同口径数据为依据。
@@ -1,5 +1,15 @@
# 2026-09-11:C 管路验证版合入网页后端
同步基线记录:将已验证的原生结果直传、浏览器Float64缓存与CSV工作线程、C端Ryu编码写出,以及八路性能调研/复现工具统一保存到 `system-optimization`。本次同步包含源代码、测试和报告;本地环境、仿真大结果和临时构建继续保留在Git忽略目录。雅可比矩阵优化从这份基线之后单独开展,沿用修正八路与 `rtol=1e-8`。
C结果编码写出优化完成:采用精确回读的Ryu数字编码与64 KiB批量写出,保留JSON结构、全量采样及binary64数值。相同修正八路,正式运行各三次,C写出1.1808→0.1638 s(-86.13%),点击到可查看8.0100→6.9756 s(-12.91%),点击到缓存保存8.1280→7.0841 s(-12.84%);CSV1.1127→1.1506 s,未观察到改善。冷编译单次3.658→4.372 s,首次网页11.682→11.381 s,已单独披露。10项编码专项、29项相关回归、8份原生结果逐位与16次网页/CSV/恢复核验通过。研究、限制、分阶段数据和复现见 [C端编码与写出报告](../other/C端结果编码与写出优化-2026-09-11.md)。未安装新环境或提交Git。
补充当前优化版八路全流程成本评估:网页预处理约19.6 ms,后台积分约6.064 s、C结果写出约1.175 s;独立原生诊断中RHS占积分93.72%,实测差分Jacobian需62,700次RHS,占全部调用84.43%。12次网页与8次原生诊断完整数值一致,本轮只增加计时工具和报告;阶段边界、CPU/墙钟、首次编译和前端采样见 [全流程成本评估](../other/八路网页求解全流程成本评估-2026-09-11.md)。
本轮结果处理优化完成:C的数值series直接进入HTTP结果流,Python不再解析并重新编码大数组;网页保存改为打包Float64块的一次原子事务,CSV改由工作线程本地生成。相同修正八路、相同精度和采样,同机旧版/优化版各预热加三次,点击到结果可查看9.872→8.034 s(-18.62%)、点击到保存完成11.774→8.132 s(-30.93%)、CSV下载保存5.610→1.005 s(-82.08%)。12次完整网页/CSV数值及刷新恢复一致;后端29项、传输6项复测、持久化6项与CSV6项专项通过。记录与实现见 [结果处理优化报告](../other/八路结果处理与网页保存优化-2026-09-11.md)。
本轮八路性能评估:后续优化优先 `test-mql-8-corrected.json`,只有八路无法运行且短期无解时才退四路。八路同精度三算法基准,当前方案纯求解 5.9138 s,相对旧固定点 12.0976 s 减少 51.12%;相同 3081320 组管阻输入重放,耗尽迭代从 3010570 次降至 0,最多 6 轮。真实网页两组各预热加三次完成;常规组点击到完成绘制中位 9.8989 s,CSV 下载 5.6198 s。已拆分后台与浏览器各阶段,并验证全部网页/CSV 数值与原生结果精确相等。当前 AME 可作保存曲线观察,但仍有早期温压和碰撞峰差异,未判八路曲线验收通过;无可信 Amesim 耗时,速度对比跳过。详见 [八路完整计时报告](../other/八路模型计算效率与网页阶段计时-2026-09-11.md) 与 [当前 AME 核查](../other/test-mql-8当前AME归档与完整曲线核查-2026-09-11.md)。本轮仅新增手动诊断和文档,未改生产算法或环境。
数据目录整理:按用户要求,`tests/data` 的 JSON/XML 仅保留可在浏览器导入、且已与对应 AME 参数和端口对齐的 `test-mql-4-corrected.json` 与 `test-mql-8-corrected.json`。其余8份资料逐字节迁到 `tests/fixtures` / `tests/baselines`;活动测试、审计脚本、CI、基准清单路径和当前报告已同步。两个工程真实浏览器导入及XML下载通过,导出的物理参数、连接和仿真设置与工程输入一致;8项路径/清单相关回归通过。具体去向见 [目录说明](../../tests/data/README.md)。
最新补充:本轮完成管流牛顿迭代的有限夹根、残差进展检查与二分回退;按用户确认将网页/API 默认 `rtol` 改为 `1e-8`。重新核对四路/八路 AME 图纸并交付 `tests/data/test-mql-4-corrected.json` 与 `tests/data/test-mql-8-corrected.json`;用户复核发现的 P4NODE2 显示方向和 3/4 号端口锚点错误一并修正。相同新精度下,相比局部半步松弛迭代,四路纯求解中位耗时 1.3309→0.9097 s(减少31.6%);72条已有Amesim参考曲线均通过原门槛,最大温差0.00882331 K。38项后端测试与2项P4真实端口几何测试通过;四路最终网页从点击到结果可查看中位3.55 s。八路修正版在新精度下单次完整完成10 s,纯求解5.91 s。最新验收范围、网页证据和八路运行限制以 [本轮完整报告](../other/牛顿管流求根与四路网页验证-2026-09-11.md) 为准;下文旧默认精度和旧输入路径为此前历史记录。