Skip to content

Fast path for self-triggered IC thinks - #1379

Open
RasmusKD wants to merge 2 commits into
EngineHub:masterfrom
RasmusKD:st-think-fast-path
Open

Fast path for self-triggered IC thinks#1379
RasmusKD wants to merge 2 commits into
EngineHub:masterfrom
RasmusKD:st-think-fast-path

Conversation

@RasmusKD

Copy link
Copy Markdown
Contributor

Every self-triggered IC pays for a full sign snapshot (getState), component serialization of all four lines and an IC id regex match on every think tick, even though the IC instance itself is already cached. At 2000 STs that measured +3.4ms per tick with spikes to 100ms.

The think handler now reuses the cached IC and family directly, and the full setupIC verification still reruns once a second per IC. The fast entry is only honoured while the IC remains in ICManager's cache, so break/unload invalidation is unchanged, and a sign edit is picked up within a second. The think itself runs exactly the code it always did (same IC instance, same sign object), so variables etc are untouched.

Chunk-loaded lookups in the ST sweep are also memoised per pass: clustered STs ask about the same few chunks thousands of times in one sweep, and a chunk cannot load or unload mid-sweep.

Re-measured after the change: 2000 active STs are indistinguishable from an idle server (50.5ms avg tick vs 50.3 baseline).

Every self-triggered IC paid for a full sign snapshot (getState),
component serialization of all four lines and an IC id regex match on
every think tick, even though the IC instance itself is cached. At 2000
STs that measured +3.4ms per tick with spikes to 100ms. The think
handler now reuses the cached IC and family directly and only reruns
the full setupIC verification once a second per IC; entries are only
honoured while the IC remains in ICManager's cache, so break/unload
invalidation is unchanged, and a sign edit is picked up within a second.

Chunk-loaded lookups in the ST sweep are also memoised per pass, since
clustered STs ask about the same few chunks thousands of times and a
chunk cannot load or unload mid-sweep.

Re-measured: 2000 active STs are indistinguishable from an idle server
(50.5ms avg tick vs 50.3 baseline).
Map<World, Map<Long, Boolean>> loadedCache = new HashMap<>();
for (Location location : registeredLocations) {
if(!location.getWorld().isChunkLoaded(location.getBlockX() >> 4, location.getBlockZ() >> 4)) {
if(!isLoadedCached(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, loadedCache)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the actual cost of checking if a chunk is loaded now? Last I checked this was functionally equivalent to a complex map lookup, which I would assume this would basically mirror.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. The measured win came from skipping the sign snapshot and the id regex, the memoisation was added on top and never measured on its own, and with isChunkLoaded being a cheap map lookup it just traded one lookup for two plus boxing. Dropped it, the checks call isChunkLoaded directly again.

isChunkLoaded is already a cheap map lookup on modern servers, so the
cache traded one lookup for two plus boxing. The measured win came from
skipping the sign snapshot and regex, which stays.
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.

2 participants