CaYaDev Server Manager v0.2.5 — the map, actually fast
The map was taking up to a minute to appear on a big world, and then losing what it had drawn the moment you panned away. Both are fixed, and both were measured rather than guessed at.
A region took 14 seconds, not 180 milliseconds (#157)
Every comment in the tile reader said a region cost about 180 ms. Measured against a realistic 4 MB region of 1024 fully-generated chunks:
inflate 83 ms 0.6%
nbt.parseUncompressed 515 ms 3.7%
tileFromChunk 13305 ms 95.7% <- nobody had measured this
The 180 ms was the decompress and the NBT parse. The surface extraction — the other 96% — had never been timed.
It was doing all per-name work per block position instead of per palette entry: a regex to strip the namespace, a lookup for air, a foliage check that ends in ten string comparisons, and a colour lookup with a second regex inside it. 4096 times per section, for a palette of at most a few dozen entries. Above the surface a chunk is about fifteen sections of pure air, and each one walked all 4096 positions to rediscover that air is air — roughly 53 000 string operations per chunk.
That is why it was worse on a big world and worse on a slower machine: both mean more generated regions, each costing 14 seconds, processed one at a time.
Now resolved once per palette entry, with an all-air section skipped before anything is unpacked or allocated. Index decoding also moved off arbitrary-precision arithmetic onto plain 32-bit integers, and only unpacks the layers the scan actually reads.
| before | after | |
|---|---|---|
| one region, cold | 13 962 ms | 1 442 ms |
| four regions, as they are queued | 38 348 ms | 6 129 ms |
| longest the interface can freeze | 584 ms | 43 ms |
| a region already in the cache | 16 ms | 13 ms |
Your existing tile cache stays valid. The rendered output is unchanged — verified by rendering 6144 chunks through both the old and the new code and comparing them byte for byte — so there is no re-parse after updating.
It threw away the ground you had just looked at (#159)
The desktop map kept the current viewport and deleted everything else, so panning one screen away deleted the screen you came from and panning back re-fetched all of it. The web map kept an 8-chunk margin, which only moved the edge. The cache limit was also smaller than a single viewport, so a wide view could evict tiles it had only just fetched.
Now nothing is dropped until the cache is genuinely full, and then the tiles farthest from where you are looking go first — what survives is a ring of the ground you have recently been over.
Two more things behind "it loads piece by piece":
- Requests were 64 chunks at a time, one at a time — 64 sequential round trips to fill one view. Now 512, so eight.
- It kept re-asking for chunks it was already waiting on. The view is walked in order, so the chunks still being read were always at the front of the next request; the map spun on one band while the rest stayed blank. Those now step aside and let the rest of the view load first.
Notes
- Zoomed a long way out the map still only draws what it already holds rather than requesting tens of thousands of chunks — but after this it holds far more than it used to. Proper downsampled zoom levels are a separate piece of work.
- Everything above ships behind the same map performance settings you already had; none of them changed meaning.
Verification: every new check in this release was deliberately broken first and watched to fail before being trusted — including a smoke gate that had been passing for months against a fixture with no terrain in it, and which fails at 661 ms on the previous release. Gates green by exit code across the spine, worlds, region-decoding, web, analysis and audit suites, and the packaged build in this release passes the full smoke.
Windows x64. The portable exe keeps all its data next to itself; the setup installs normally.