Skip to content

Cache the fake render environment used by game scenes - #123

Open
julian-perge wants to merge 1 commit into
AppliedEnergistics:mainfrom
julian-perge:fix/cache-fake-render-environment
Open

julian-perge wants to merge 1 commit into
AppliedEnergistics:mainfrom
julian-perge:fix/cache-fake-render-environment

Conversation

@julian-perge

Copy link
Copy Markdown

Fixes #106

GuidebookLevelRenderer#renderContent calls FakeRenderEnvironment.create()
once per visible scene per frame, and every call builds a fresh Connection,
ClientPacketListener, ClientLevel and LocalPlayer before close() throws
them away again.

There is a second cost beyond the allocation. Constructing ClientPacketListener
bootstraps PotionBrewing, which fires RegisterBrewingRecipesEvent, and
constructing ClientLevel fires LevelEvent.Load. Any mod that listens to
either one redoes its registration work on every frame that a scene is visible.
In my ATM11 alpha mod-pack I counted just over 52,000 such registrations from three mods
in a single session, peaking at 419 per second while an AE2 guide page was open.
They accounted for 95% of the lines in my logfile.

The fake player does not depend on the scene being rendered. create() already
ignores its Level parameter, which is what makes caching safe here. It now
keeps the built graph in a static field next to the RegistryAccess it was
built from, and rebuilds only when Platform.getClientRegistryAccess() returns
a different instance. The rest of create() is untouched, including the
minecraft.player swap that close() reverts.

That is the approach @LegendaryRylex described in #106. On top of it,
GuideMEClient clears the cache on ClientPlayerNetworkEvent.LoggingOut, so
leaving a world does not pin that world's RegistryAccess.

I tested this on 26.1.2 in the pack described above. The registrations now
happen only at world join, and the guide pages that used to produce the bursts
no longer do.

#121 rewrites the same method while porting to 26.3, so whichever of the two
lands second will need a small rebase.

GuidebookLevelRenderer#renderContent calls FakeRenderEnvironment.create() once
per visible scene per frame, and each call built a fresh Connection,
ClientPacketListener, ClientLevel and LocalPlayer before close() discarded them.

Besides the allocation, constructing ClientPacketListener bootstraps
PotionBrewing, which fires RegisterBrewingRecipesEvent, and constructing
ClientLevel fires LevelEvent.Load, so every mod listening to either event redid
its registration work on each frame a scene was visible.

create() ignores its Level parameter, so the fake player does not depend on the
scene being rendered. Keep it in a static field next to the RegistryAccess it
was built from and rebuild only when Platform.getClientRegistryAccess() returns
a different instance. GuideMEClient clears the cache on
ClientPlayerNetworkEvent.LoggingOut so leaving a world does not pin that world's
RegistryAccess.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[26.1.2] Game scenes rebuild the entire fake client environment every frame

1 participant