Making the world faster without changing a thing

← All field notes

There is a tidier kind of performance work than the dramatic kind. No bottleneck hunt, no surprising hotspot — just five small changes to the part of the world that ticks creatures and grows plants, each chosen so it computes the very same values, in the very same order, with less wasted work. And then the part that mattered most: proving, beyond doubt, that the world hadn’t moved at all.

We have told the other side of this before. Once, a speed fix quietly moved the whole world — a change meant only to free up frames ended up feeding more animals, and we let the new balance stand. This is the optimistic twin of that story. The goal here was the opposite: go faster and prove that nothing changed. In a world built to unfold the same way every time, that proof is not a footnote. It is the deliverable.

Why “same answer, faster” is even a thing you can prove

The Long Watch is deterministic on purpose: feed it the same seed and the same inputs and it produces exactly the same world, down to the last detail. We lean on that property hard — a living ecology that stays byte-for-byte reproducible is a story of its own — but the part that matters here is the consequence. Because the world is reproducible, a change can be held against a trusted reference and judged identical or not, value for value — the same comparison we leaned on to prove an earlier speedup changed nothing. That is what turns “I think this is faster and still correct” into something you can actually demonstrate.

It also sets the bar. An optimization isn’t allowed in just because it’s faster; it’s allowed in only if it can be proven to compute the same values in the same order. Reorder a sum, round one step differently, draw the same dice in a different sequence, and the world drifts — subtly at first, then into a different forest entirely. So every change below was held to one rule: less work, identical result.

Five quiet speedups

None of these is clever in the way a good algorithm is clever. They are all the same humble move — stop doing work the world was doing out of habit — applied in five different corners.

Reuse the list instead of rebuilding it. The simulation keeps a list of where things are, and it had been rebuilding that list from scratch every cycle. Now it reuses a cached copy — but only when the cache is guaranteed to still match what’s on the ground. The safety is the whole point: a cache you trust unconditionally is a bug waiting to happen, so this one is trusted only in the exact conditions where it cannot have gone stale.

Read from the live world instead of copying into a snapshot. Each pass had been copying a couple of bookkeeping columns into a working snapshot before reading them. Those particular values can’t change underneath the pass while it runs, so we stopped making the copy and read them straight from the live store. Same numbers, one fewer round-trip through memory.

Reuse the scratch memory. Several passes had each been allocating their own fresh working buffers every cycle, using them, and throwing them away. Now they share one block of scratch memory across passes. Allocating and freeing nothing is faster than allocating and freeing constantly, and the arithmetic that happens in that scratch is bit-for-bit what it was.

Don’t paint a world nobody is watching. When the simulation runs with no display attached — which it does often, during the long unattended runs we use to study how a world behaves — it had still been rebuilding the on-screen visual representation of everything, frame after frame. That work is purely invisible in that mode. Now it simply doesn’t happen when there’s no screen to show it on. Nothing about the simulated world changes; we just stopped drawing to an empty room.

Sample the ground once, not three times. Every plant, on every growth step, had been making three nearly-identical lookups of the same patch of ground beneath it. We consolidated them into a single shared sample. For one plant that’s trivial; across a field of thousands, on a beat that runs several times a second, the redundant world-querying added up.

A small patch of voxel meadow at golden hour seen from just above, a few grass plants rooted in soft soil with the world fading to warm haze at its edges.Concept art · pre‑alpha
One patch of ground, sampled once instead of three times — the same answer, less fuss, for every plant on every step.

The deliverable was the green light

Here is the part that distinguishes this from ordinary tidying. After all five changes, we ran the checks against the trusted reference and they stayed green. The creatures lived and died the same. The plants grew the same. The soil and the slow work of decay behaved the same. Not “close enough” — identical.

That green light is the whole point. The reason any of these five is worth keeping is that we can show it changed nothing — the optimization isn’t the speedup, it is the speedup plus the proof that the world didn’t notice.

The proof that an optimization changed nothing is the deliverable. The speed is just what you get to keep once you’ve earned it.


The shortcut we threw away

The honest companion to five wins is one dead end, and this effort had a good one. We spend a lot of time on long, unattended runs to tune the feel of a world — balancing the whole ecosystem by running it again and again takes patience — and those runs are slow. So we tried a measurement shortcut: shrink the playable area, and a long test run finishes several times faster — we were aiming for something like four to nine times. Cheaper runs, faster tuning, more loops of learning per afternoon. It was a tempting idea.

It didn’t work, and the failure was instructive. Shrinking the world changed the kind of world it was. In the full-size world, life is limited by crowding — it fills out and settles, running out of room long before it runs out of food. The tiny world died of something else entirely: the food collapsed too early, and the founding pair starved out before they could establish themselves. A run that dies of starvation tells you nothing reliable about a world whose real constraint is crowding. The little world wasn’t a faster copy of the big one; it was a different experiment that happened to use the same code.

So we abandoned the shortcut and went back to tuning against the real, full-size runs — slower, but the only ones that reproduce the dynamics we actually care about. We left the harmless groundwork that the shortcut had needed in place, because at its default it changes nothing; only the shortcut itself went in the bin.

The one we left on the shelf

There is a tempting speedup still sitting untouched, and it’s worth saying why we haven’t taken it. Of all the changes that would make the simulation faster on this provably-identical footing, the most attractive remaining one isn’t safe: it could quietly break the guarantee that a saved world reloads exactly as it was put down. That guarantee is the one property this entire effort rests on — the same reproducibility the green checks measure, extended across the gap of closing a file and opening it again.

We could probably make it work. We could probably even convince ourselves it was fine. But “probably fine” is exactly the bar this kind of work exists to refuse. A speedup that might move the world is not a speedup we get to keep, no matter how good the numbers look. So it stays on the shelf, where a tempting-but-unproven change belongs, until we can prove it the way we proved the other five — or decide we never will.

That is the quiet discipline underneath all of it. Going faster is easy. Going faster while being able to look someone in the eye and say nothing moved is the part worth the work.

Keep reading

Concept art · pre‑alpha