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

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 → 62msensure_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.rspackages/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.tomlearlyWindowControl 该整合包下与 mod 冲突导致更慢11s → 30s已回滚

构建

# debug含计时埋点、文件日志
cargo build -p theseus_gui

# release
cargo build --release -p theseus_gui
Description
实例启动动画
Readme 115 MiB
Languages
JavaScript 54.8%
Rust 20.3%
Vue 12.3%
TypeScript 8.4%
HTML 1.8%
Other 2.2%