Skip to content

优化模组列表刷新性能:缓存解析结果与图标 - #6869

Open
xianaldai wants to merge 1 commit into
HMCL-dev:mainfrom
xianaldai:perf/modlist-refresh-cache
Open

xianaldai wants to merge 1 commit into
HMCL-dev:mainfrom
xianaldai:perf/modlist-refresh-cache

Conversation

@xianaldai

Copy link
Copy Markdown

改动

解析一个模组要打开它的压缩包、读取元数据条目,而每次刷新都对每个模组重做一遍。现在按文件
大小和修改时间缓存解析结果,未改动的模组列表刷新只需一次 stat

为此读取器改为返回 LocalModFile.Metadata(新增的嵌套 record),而不是 LocalModFile
后者绑定在管理器上、并把自己注册进对应的 LocalMod,无法跨刷新复用。
读取器的方法名和参数顺序保持不变。

刷新会把每个 ModInfoObject 重建一次,挂在条目上的图标于是被丢掉、下次再打开 jar 解一遍。
改为把图标挂在页面上,以路径、大小、修改时间和加载器类型为键。

实测

268 个模组:

场景 上游 本 PR
再次刷新(文件未改动) 240-751 ms 12-94 ms

收益来自缓存:文件大小和修改时间未变时不再打开压缩包,每个模组只剩一次 stat

图标解码此前实测占刷新开销的绝大部分(29 个可见图标、589.6 ms),本 PR 让重建条目时复用
已解码的图标。

Parsing a mod file opens its archive and reads its metadata entry, and every
refresh of the mods directory repeated that work for every mod, even when
nothing had changed. Parse each file once and cache the result keyed by its size
and modification time, so a refresh of an unchanged directory only stats the
files. Parsing also no longer runs on the manager lock, which lets the files be
parsed in parallel on the first refresh.

To make that possible the metadata readers return a new LocalModFile.Metadata
value instead of a LocalModFile. A LocalModFile is bound to its manager and
registers itself with the LocalMod it was created for, so it cannot be built off
the manager lock nor reused across refreshes; the owning manager builds it from
the parsed value when it merges the results.

Two other things the parse phase was wasting time on:

- ZipFileTree.getEntry falls back to indexing every entry of the archive
  whenever a name is absent, and the readers probe for optional entries
  constantly. Look those up in the reader's own name index instead.

- A reload of the mod list rebuilds every item, so an icon held on the item was
  decoded again on the next reload. Hold the icons on the page, keyed by path,
  size and modification time, and let a rebuilt item reuse the icon already
  decoded for its file.
@github-actions github-actions Bot added the 100+ label Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant