All the unexpected attention on Global Thermonuclear War over the last couple of weeks gave me some interesting problems to solve. Simulated nuclear armageddon isn’t exactly one of the Google Maps team’s key use cases that they cater for. Here’s one of the many dirty tricks I pulled to mitigate the horrendous slowdown that plagued the game in its first couple of days.
The simplicity of Global Thermonuclear War’s multiplayer code is a double-edged sword. New players only see missile launches reported after their arrival. So everyone starts out with a pristine world, unspoilt by nuclear war. Only after a player sticks around for a while do launches and explosions accumulate on their map.
When the game gets really busy, the air quickly fills with missiles. People arrive, figure out what’s going on, and then immediately unleash hell. At its peak, the game has been dealing with almost 200 simultaneous players. That’s a lot to deal with when your graphics library isn’t designed for building real-time 2D multiplayer games.
Broadly speaking, the more missiles in the air, the slower the game runs. It’s a vicious circle, because slower missiles take more time to reach their target. After a certain point, the missiles are barely moving at all, and new ones keep getting fired. The game crawls to a halt and the only fix is to refresh the page.
The last three paragraphs amount to one very awkward problem: missiles move faster for newly-arriving players than for those who’ve been playing for five minutes or more. If you’ve just arrived, your map’s empty and everything is running optimally. If you’ve been playing a while, you’ve probably got a few dozen missiles moving across the map. For the new player, a missile will travel across the map and arrive at its destination much, much faster.
I spent a lot of time last week trying to fix this. That desynchronisation effect is annoying and I wanted to eradicate it. I tried various “clever” optimisation tricks that didn’t really go anywhere. Just as I was about to give up, something hit me. I might not be able to influence the speed of the game when there are a lot of missiles, but I can control the speed of the missiles themselves. So that’s what I did.
var speed = 1000 + Math.min(this.missiles.length * 10, 999);
This line of code makes missile speed proportional to the number of missiles visible on the map. The more there are, the faster they move. When there are 100 or more missiles in the air, their speed is nearly double the base rate.
This is more like a painkiller than a cure. It doesn’t fix the problem, but it conceals its subjective effects. The game still slows down when it’s busy, but the faster missile movement compensates slightly.
There are lots of reasons why this absolute hack of a solution is bad. For one, it’s based on absolutely zero proper benchmarking work. For all I know, this probably backfires horrendously on beefy gaming rigs that don’t need the helping hand. Combine this speed-up effect with none of the graphical slow-down, and your nuclear conflict takes on an unwanted slapstick comedy effect.
Concerns about software engineering rigor aside, there are two things about this
hack that I like. Mainly, it was quick and easy to get it built at eight o’clock
in the morning before leaving for work. And secondly, I actually like how
symbolic it is of so much of the code I’ve written for this game. It’s just such
fun code. The test coverage may be poor (0%), but the quality’s okay
and it’s full of crazy shit like
launchMissile: function(missile) and
missile.detonate(). It’s been a break from my usual “Serious Business”
approach to building stuff, and that’s a break I guess I must have needed.