Files
Starlight_Lancher/README.md
Xiao-no-love ccb921f4bd perf: 优化实例启动性能并修复过渡动画对齐
依赖校验戳缓存(18.6s→0.1s)、并发化库/资产校验、启动计时埋点、过渡动画200ms、窗口客户区精确对齐、遮罩即时显示、debug构建写文件日志。
2026-09-16 13:10:37 +08:00

98 lines
4.3 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.

# Starlight Launcher — 实例启动性能优化记录
> 内部文档,非上线说明。本分支聚焦「实例启动慢」问题的定位与修复。
## 背景
用户反馈:点击实例启动后,要等很久才看到游戏窗口。
经实测定位,问题由多个独立环节叠加造成,本分支逐项修复。
## 改动清单
### 1. 依赖校验戳缓存(`packages/app-lib/src/launcher/direct_ensure.rs`
**问题**PCL/HMCL 直连实例每次启动都要对全部库文件与资产对象重算 SHA1。
实测某整合包118 个库 + 3911 个资产对象,合计约 670 MB机械硬盘顺序读仅
27.8 MB/s串行校验耗时约 **17.7 秒**,占整个启动准备阶段的 97%。
**方案**新增持久化「已验证」戳缓存key 为文件绝对路径value 为
`(size, mtime)``file_is_current` 先做 stat命中戳则跳过 SHA1 读取;
文件被替换或修改size/mtime 变化)时自动回退到完整 SHA1 校验,**不弱化
损坏检测**。
- 缓存文件:`<caches>/linked-verify-stamps.json`(存 Axolotl 自己的缓存目录,
不污染直连安装目录)
- 首次启动建立缓存仍走完整校验;后续启动(含跨进程重启)直接命中
**效果**`asset_scan` 15788ms → 62ms`ensure_deps` 整体 18.6s → 0.1s。
### 2. 库/资产校验并发化(`packages/app-lib/src/launcher/direct_ensure.rs`
在戳缓存基础上,把库扫描与资产扫描从串行 `for` 循环改为
`try_for_each_concurrent`(并发度与下载器一致,`task_concurrency_limit * 2`)。
首次建缓存时也能吃到并发收益。
> 并发对机械硬盘的随机小文件读取提升有限IOPS 瓶颈),真正的
> 数量级提升来自上面的戳缓存。
### 3. 启动阶段计时埋点(`packages/app-lib/src/api/instance/run.rs`、`packages/app-lib/src/launcher/mod.rs`
在启动链路插入 `[launch-timing]` 前缀的计时日志,覆盖:
`hosted_prepare_launch` / `hosted_java_arguments` / `resolve_version_info` /
`resolve_java` / `resolve_gc` / `assemble_client` / `ensure_deps`(细分
`dep_lib_scan` / `asset_scan` / `dep_assets` / `dep_log_config`/
`remove_old_natives` / `extract_linked_natives` / `process_spawn`
用于定位瓶颈grep `[launch-timing]` 即可。
### 4. 启动过渡动画优化(`apps/app/src/mc_transition.rs`
**a. 动画时长**400ms → 200ms帧数 50 → 25。缓解卡顿。
**b. 窗口对齐修复**:全屏放大与缩回游戏窗口时,左侧留缝、整体偏右。
根因是无边框窗口的不可见 resize border实测窗口比目标大 16×9px
可见内容从 (8, 4.5) 才开始)。改用 `set_client_rect`,通过
`GetWindowRect` / `GetClientRect` 计算边框并补偿,让**可见客户区**精确
落在目标矩形。
**c. 单次 SetWindowPos**:每帧从两次调用(`set_position` + `set_size`
改为单次 `SetWindowPos`,减少重绘。
**d. 恢复可见**:动画前先 `show()` + `unminimize()`,避免轻量模式遗留
导致遮罩建了却不可见。
### 5. 遮罩即时显示(`apps/app/src/lightweight_mode.rs`
**问题**:点击启动后遮罩要等约 10 秒才出现。
**根因**:收到 `launched` 事件后,代码先 `await maximize_minecraft_window`
(最多轮询 5 秒等游戏窗口),跑完才启动遮罩动画。
**方案**:把最大化游戏窗口丢到独立任务,遮罩动画立即启动,两者并行。
### 6. debug 构建写文件日志(`packages/app-lib/src/logger.rs`
**问题**debug 构建的 `start_logger` 只输出到控制台、不落盘GUI 进程
关闭后无法回溯日志,导致性能计时无法采集。
**方案**debug 版 logger 增加一层文件输出,写入与 release 相同的
`launcher_logs` 目录,文件名带 `session_debug_` 前缀。
## 结论与边界
- **启动器侧**:准备阶段已从 18.6s 优化到约 0.1s,拉起进程约 0.6s,已到极限。
- **游戏侧**:窗口出现前约 11s、完整加载约 45.8s230 mod 的 NeoForge 整合包),
属整合包固有成本,任何启动器无法缩短。
- 曾尝试开启 NeoForge 早期窗口(`fml.toml``earlyWindowControl`
该整合包下与 mod 冲突导致更慢11s → 30s**已回滚**。
## 构建
```bash
# debug含计时埋点、文件日志
cargo build -p theseus_gui
# release
cargo build --release -p theseus_gui
```