perf: add per-tick occupied-chunk cache to short-circuit entity queries#633
Closed
Rail1bc wants to merge 2 commits intoryanhcode:mainfrom
Closed
perf: add per-tick occupied-chunk cache to short-circuit entity queries#633Rail1bc wants to merge 2 commits intoryanhcode:mainfrom
Rail1bc wants to merge 2 commits intoryanhcode:mainfrom
Conversation
Adds a LongSet-based cache of every chunk position occupied by at least one sub-level. The cache is rebuilt from scratch each tick in SubLevelContainer.tick() and provides O(1) lookups via the new isChunkOccupied(chunkX, chunkZ) method. This cache is consumed by SubLevelInclusiveLevelEntityGetter to skip the full sub-level traversal when the queried AABB demonstrably does not intersect any sub-level, dramatically reducing per-call overhead.
Before entering the full sub-level-aware traversal, check whether the queried AABB actually overlaps any sub-level by consulting the per-tick occupied-chunk cache. If the region is free of sub-levels the call is forwarded directly to the vanilla delegate, bypassing all Sable wrapper overhead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds a per-tick occupied-chunk cache that enables O(1) lookups for "does this chunk contain a sub-level?" queries. The cache is consumed by
SubLevelInclusiveLevelEntityGetterto short-circuit the expensive sub-level traversal when the queried AABB clearly does not intersect any sub-level at all.Background
Issue #510 reports that
SubLevelInclusiveLevelEntityGetter.get()is extremely slow (>50ms per call vs <0.1ms for vanilla) because every invocation ofget(AABB)iterates over all loaded sub-levels — even when those sub-levels are nowhere near the query region. On servers with many chunks and entities this adds up to severe tick-time regression.Changes
SubLevelContainer.javaLongSet occupiedChunksfield — a set ofChunkPos.asLong()-encoded chunk positions that are covered by at least one loaded sub-level.tick()so that moving/rotating sub-levels are tracked correctly.isChunkOccupied(chunkX, chunkZ)— public O(1) query method backed by the cache.SubLevelInclusiveLevelEntityGetter.javahasSubLevelInAABB(AABB)helper that performs a two-level short-circuit:get(AABB, Consumer)andget(EntityTypeTest, AABB, ...)now return early via the vanilla delegate when no sub-level intersects the query region.Performance Impact
The cache rebuild itself costs O(m·s) per tick (m = sub-level count, s = chunks per sub-level), which is negligible compared to the O(n·m) it eliminates across the thousands of
get(AABB)calls per tick.