MC-249136 was fixed in 24w04a by checking a structure placement's cheap seed math before running the expensive generation-point calculation. That fix stopped short of the other expensive step: the disk read runs even earlier, and the cheap check never gets the chance to prevent it.
In StructureCheck.checkStart (Mojang mappings, 26.1.2) the order is:
loadedChunksin-memory cachetryLoadFromStorage- a region-file scan of the chunk's NBT plus a partial DataFixer pass, ending in a blocking join on the storage IO workerStructurePlacement.applyAdditionalChunkRestrictions- the frequency check from the 24w04a fix: one seeded random call, effectively freecanCreateStructure- the biome/generation-point math the 24w04a fix guarded
Step 2 runs before step 3. For every structure set with frequency < 1.0 (pillager outposts at 0.2, mineshafts, buried treasure, nether fossils, several others), the majority of candidate chunks are rejected by step 3 - but each of them has already paid a region-file read and a datafix attempt in step 2. For buried treasure (frequency 0.01) more than 99 of every 100 scanned chunks are discarded by a check that costs nanoseconds.
This cost is paid by every caller of checkStructurePresence: the /locate command, exploration map generation (cartographer trades and loot chests), and eye of ender throws.
The scan in step 2 also has a permanent side effect that makes its cost more than time: RegionFileStorage.getRegionFile opens region files with StandardOpenOption.CREATE, so every scanned candidate chunk in ungenerated terrain leaves an empty 0-byte .mca file in the world save. A single wide locate can create hundreds of them. Rejecting candidates before the scan avoids that too.
What I expected: The free rejection checks run before any disk IO, as 24w04a already established for the generation-point math.
A note on the fix shape: Simply moving step 3 above step 2 would change behavior: disk contents are currently authoritative, so a start that exists on disk in a chunk the current placement math vetoes (possible after a datapack changes a set's frequency or salt mid-world) is found today and would become invisible after a plain reorder. A shape that keeps current behavior exactly: before the full scan and datafix in step 2, consult the region file's chunk-presence header (a lookup with no decompression and no datafix). A chunk that does not exist on disk cannot contain a start, so the full scan and the datafix can be skipped for it with no behavior change - and candidates in ungenerated terrain are the overwhelming majority of what a locate examines.
How to observe: Run /locate structure minecraft:pillager_outpost in a fresh world and inspect the "Locating element ... took ... ms" server log line, or profile the command: the time is dominated by tryLoadFromStorage calls for chunks that step 3 rejects immediately afterwards.
Environment
Not relevant - platform-independent code path issue.
Linked issues
relates to 1
Comments 3
Re-verified on 26.3 Snapshot 10, in code and empirically: the ordering is unchanged. tryLoadFromStorage still runs before applyAdditionalChunkRestrictions on the first check of any chunk.
What the MC-310693 fix did add: repeated checks of the same chunk now skip the scan (a capped negative cache), and reads no longer create region files, absent regions are cached as a plain existence check. That fixes the empty-file side effect and makes ungenerated terrain much cheaper: same seed and commands on both versions, the outpost locate drops from 220 ms to 49 ms and the empty 0-byte files from 82 to none.
Still present: candidates in generated terrain pay the full NBT parse and datafix attempt before the frequency check, so for frequency < 1.0 sets most parses on a first pass over explored terrain are discarded right after.
Thanks for replying, I’ve set this to Plausible. Hopefully it does get fixed this cycle to further mitigate MC-250276, benefiting the new structure maps.
Is this issue still present (and your code analysis still valid) in 26.3 Snapshot 10, or was the issue alliviated along with MC-310693?