Skip to content

perf(i18n): cache parametrised renders and reuse action snapshot factory - #128

Merged
Arbousier1 merged 3 commits into
devfrom
codex/perf-i18n-render-cache
Aug 5, 2026
Merged

perf(i18n): cache parametrised renders and reuse action snapshot factory#128
Arbousier1 merged 3 commits into
devfrom
codex/perf-i18n-render-cache

Conversation

@Arbousier1

Copy link
Copy Markdown
Collaborator

Summary

Spark 采样(https://spark.lucko.me/j9YE2XtMP3)显示每 tick 观众渲染大量时间花在 LocalizedMessages.plain 的 MiniMessage 反序列化(renderWithTags/deserialize 热点,MessageService.plain 栈)与 G1 分配(allocate_new_tlab 热点)上。

三个改动(行为不变):

  1. Map 版渲染缓存LocalizedMessages.render/plain(Locale, key, Map) 现按 (locale, key, 排序后的占位符条目) 用 Caffeine(max 512)缓存;热路径 publicSeatStatus/publicCenterText/botDisplayName 每 tick 只对稳定占位符集反序列化一次。占位符按 tag 名解析,Map 迭代顺序不影响输出;bundle 加载后不可变。
  2. MessageService 门面补齐render/plain(Locale, key, Map) + formatNumber 委托,热调用方无需构造 TagResolver 数组。
  3. PlayerActionSnapshotFactory 复用:每 session 一个(原先 GbBot 每 tick new 3 次 + Sichuan 1 次),GbBotStrategy.hasAction stream → for 循环。

门禁

性能 label:performance-ab + performance-i18n(i18n profile 为 PR-A #126 新增,含 bot-name / seat-status / center-text 等带占位符渲染基准)。

Test plan

  • 本地 compileJava(JDK 25 toolchain)通过
  • 本地 i18n + BotStrategy 测试通过(-PmahjongJavaTarget=25,getFirst 需要 Java 21+ API)
  • CI test.yml 全量
  • i18n 权威 A/B 门禁 PASS_OPTIMIZED

Spark sampling (j9YE2XtMP3) shows per-tick viewer rendering spends its
time in MiniMessage deserialization under LocalizedMessages.plain with
placeholder TagResolvers:

- Cache Map-based render/plain by (locale, key, sorted placeholder
  entries) via Caffeine (max 512): hot paths publicSeatStatus,
  publicCenterText and botDisplayName now hit a single deserialize per
  stable placeholder set instead of per tick.
- Add formatNumber + Map overloads to MessageService facade so hot
  callers can use the cached path without constructing TagResolvers.
- Reuse one PlayerActionSnapshotFactory per session (was 3-4 news per
  bot tick) and replace hasAction stream().anyMatch with a plain loop.

Behaviour is unchanged: placeholder maps are resolved by tag name, so
iteration order does not affect output; bundles are immutable after load.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@Arbousier1 Arbousier1 added performance-ab Run the base-owned paired performance gate performance-i18n i18n benchmark profile (message rendering) labels Aug 4, 2026
BotActionSchedulerTest and SichuanBotPreparationSchedulerTest mock
MahjongTableSession, which now exposes actionSnapshotFactory(). Stub it
to return a real PlayerActionSnapshotFactory so the shared per-session
factory path is exercised by the scheduler tests.
@Arbousier1
Arbousier1 merged commit cde8917 into dev Aug 5, 2026
11 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance-ab Run the base-owned paired performance gate performance-i18n i18n benchmark profile (message rendering)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant