snowoar

Snake Legends

Made a laggy multiplayer game run smooth — and published the optimization that failed.

A live multiplayer game where players control snakes that grow as they eat. The more players and the longer the snakes, the more work the game has to do every single frame — and past a certain size, it stuttered.

I spent weeks measuring where the time actually went. The most useful thing I found was that my own first fix made it worse.

The optimization that failed

The obvious move was to spread the work across multiple CPU cores. I built it, measured it, and it came out at 16.95 ms per frame against about 6 ms for the original — three times slower.

The reason: I had moved the cheap half of the work onto other cores, and the cost of shipping data back and forth — roughly 8,700 individual writes per frame — was larger than the work I had moved. I wrote up the result, left the branch unmerged, and went looking for the real bottleneck.

Finding the real bottleneck

Measured at 865 body segments: the math took 6.07 ms, but applying the results to the game world took 9.14 ms. That second number was the problem, and it could not be moved off the main thread at all.

So the fix was not "use more cores" — it was "touch fewer objects."

What actually worked

The bug underneath the bug

Two separate root-cause writeups assumed the background worker was running. It never had been: it waited forever on an object lookup that could not resolve once the code was copied into a worker at runtime. Everything measured before that discovery was measuring the wrong thing.

Why this one matters to me

Shipping the failed experiment was more useful than hiding it. It is the reason I found the real bottleneck instead of optimizing something that was never the problem.