Ik was middag aan het pauzeren en ik kwam ineens op een idee om iets te maken en dan heb ik daar dan maar een design voor geschreven en de AI in de buurt op weg gezet.

Het is redelijk meditatief om mijn artificiële medewerker op de achtergrond te zien met zichzelf overleggen:

Now I’m designing the resampler logic: for each source, I’ll check if it’s cell-registered on the same origin with resolution that’s an exact multiple or divisor of the ring resolution and bounds that align — if so, I can use exact block reduction or replication. Otherwise I’ll fall back to rasterio’s reproject function, which handles the general case cleanly.

Actually, using `warp` with `Resampling.average` everywhere is simpler and correct, even for aligned grids. The real concern is memory and time on huge sources like GEBCO’s 3.7 billion cells, but `rasterio.warp.reproject` streams from the band source so it should be manageable. A faster path for exact integer factors is GDAL’s RasterIO decimation via `ds.read(out_shape=…, resampling=Resampling.average)` — that’s streaming and efficient, and for the globe covering the whole world it works directly.

[…]

I’m noticing the tiles have varying resolutions across latitude bands—the N48 and N49 tiles sit in the 0-50° band while N50+ are in the 50-60° band with different longitude resolution. `rasterio.merge` can handle this by resampling to a target resolution, but I’m also considering warping each tile individually into the destination ring array, writing only where data exists.

Reconnaissance paid off — four sources aren’t aligned the way the plan assumed, and HYDE’s own header is subtly wrong. Now I can write the resampler against facts.

Enzoverder, enzovoort. Ik heb een enorm ambitieus plan — zijn ze dat niet allemaal? — maar ik begin met een MVP, en als ik wakker word zie ik het werk van de nacht staan:

Big night. Summary of what happened after you went to bed:

The 4-hour soak completed with all of tonight’s changes. Frame health: flawless — pinned at the 33.3 ms cap for the full 4 hours with zero degradation, and the 5× wildlife update cadence costs nothing measurable. But the P0 memory climb reproduced: 95.7 → 190.5 MB at ~22 MB/h, r = 0.992.

Then I diagnosed and fixed P0. Two new bisection probes did it:

  1. node_census.gd exonerated the scene tree — node counts fluctuate both directions with chunk density, no leak there.
  2. mem_probe.gd ran the sim with no scene tree at all and still leaked — and only during daytime walking hours, dead flat overnight. That’s the signature of a per-cell cache growing with ground covered.

The culprit: DetailField._scatter_cache — an unbounded memo of every 4 gm scatter cell ever queried (~23M possible keys, never evicted). The Brain’s steering probes grow it while walking; every chunk build permanently caches ~64+ more cells, which is why the rendered soak leaked ~6× faster than pure sim. The fix is a cap with oldest-half eviction (insertion order = the ground farthest behind the walk). Since the cache is a pure hash-based function of the world seed, eviction is deterministically safe — and verified: the memory probe now sawtooths in a ~48–56 MB band instead of climbing (+11.4 MB at end vs +52.6 and rising), the event log is identical, fir_probe reproduces its daily distances bit-for-bit, and both suites are green.

A 45-minute rendered soak is running now to confirm the render path plateaus too; a watcher will pull me back to check it. Implementation log and memory are updated. Nothing is committed — say the word in the morning and I’ll commit the lot.

Ik weet nu al dat ik het ergens in de loop van het project ga loslaten en dat het op de enorme stapel “ooit eens, dan eens” terechtkomt, maar ondertussen heb ik wel vertier gehad. 🙂



Reacties

Zeg uw gedacht

Deze site gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie gegevens worden verwerkt.