I am not Colt McAnlis. If I were, I would recognize that my luscious locks of hair interfere with heat exchange over my primary processing cores, getting in the way of optimal performance, and remove them. However, I am a great fan of his talks and YouTube videos on performance in Android apps. They form the bedrock understanding of Android requirements on which all the rest of my Android knowledge is built.

And that is why, as I sit here staring at the server error message screen on Pokémon GO, I am certain that Colt McAnlis, wherever he is, is fuming. Because from my experience with the game, Niantic set out with the primary goal of proving that they could create a successful game while ignoring every one of Android’s (and mobile development in general’s) performance best practices.

The game could be made not just better, but significantly better and cheaper to maintain by more aggressive use of prefetching and caching.

By its very nature, Pokémon GO was always going to be a strain on your phone. It requires extended periods of active interactions, it makes heavy use of your data antenna and your GPS and it uses your accelerometer and camera in one of its core functionalities. But the phenomenal rate at which it drains battery power while simultaneously failing to provide a fluid and robust experience points to some deeper issues, and ultimately a failure to make simple modifications to provide better performance and a better user experience. The game could be made not just better, but significantly better and cheaper to maintain by more aggressive use of prefetching and caching.

Caching User Data

When the game starts, you are presented with a splash screen with the developer’s logo on it. Fair enough, this is pretty standard in phone games. But then you are also presented with a loading screen with a progress bar. This loading screen does have the nice touch of a cute image featuring a Gyarados and a warning not to walk into traffic, but it takes forever. And it’s a screen players have come to dread because this is where you find out if you were able to log in to the game’s servers or not. The loading bar seems to be broken up into about four or five segments. If it fails at the first segment, you get a message that the app was unable to log in to the app servers. If it fails at the second segment, it notifies you that it was unable to download player data from the server. From this I deduce that this second loading screen is used to load in player data such as name, caught Pokémon, avatar appearance, etc. Why? You can’t change your player’s name or appearance. You can’t make any changes from a desktop. You can’t catch or hatch Pokémon while the app is closed. The only possible way any of this could have changed is if you are playing on multiple devices. Let’s consider two usage scenarios: In the first scenario, a.k.a. real life, they require a login and data refresh to be able to play the game, and there is a server issue, or the player loses connectivity. The result is that the player gets a long loading screen followed by an error message and is unable to play the game. They complain on Twitter, they write blogs, they rant on Facebook and they leave bad reviews for your app in the store. In the second scenario player data is restored from the cache on login, and refreshed from the server asynchronously. In this scenario, a very small percentage of the player base might experience a situation where they catch a Pokémon on their phone, and have to wait a few minutes before it shows up on their tablet. For everyone else the game loads twice as fast, with no error messages, and there is no perceptible difference in game play. And we’d be able to read our Pokédex or check on our eggs instead of writing blogs. On the other side of things, allow gameplay even if we can’t reach and authenticate the servers. We can hold any changes locally, and upload them when access becomes available again. Again, the cost is only to users who play on more than one device, and it’s a pretty small cost at that.

Prefetching Pokémon Locations

Pokémon GO is not just a battery intensive game, it is the single largest drain on a mobile battery I have ever seen.

While the game is running, it makes constant use of your cellular or wifi antenna to synchronize with the servers and determine whether or not there are nearby Pokémon and if they’ve already been caught and so forth. This is clearly a key component of the game. One of the things they advertise is that you see the same Pokémon as other players around you, and this contributes to the social aspect of the gameplay. When it works, it’s really quite nice. But there are two major problems with this approach, and they could both be easily solved with a minor sacrifice. The first is that this always-on approach to the antenna is eating up your battery. The cellular antenna is the second most expensive component on your phone in terms of power, right after your large, super-bright and colorful AMOLED display. After frequent server failures, this is the second biggest complaint against Pokémon GO on review sites. My battery used to last me all day and then some. With Pokémon GO active, even when it is not in the foreground, my battery barely lasts until lunch. Pokémon GO is not just a battery intensive game, it is the single largest drain on a mobile battery I have ever seen. And what do you get for sacrificing your precious battery life? If internet near you is anywhere near as flaky as it is around my apartment, you get a lot of Rattatas you can’t tap on, frozen screens, blank Pokéstops and so, so much of that spinning white Pokéball. Pokémon GO is always fetching everything from its servers to make sure that your experience is synched up with players around you. But that means that any drop in data service translates directly into lost game performance. That sucks enough if you’re in the suburbs with flaky 3G, but when Niantic rolls out to the rest of the world they’re gonna have a bad time. Both of these problems could be solved with a modicum of prefetching and caching. The battery usage of the cell antenna and optimal prefetching is surprisingly complex, but to throw out a ballpark if the game only fetched updates every 30 seconds, instead of continuously as it appears to do now, you could reduce battery consumption in the neighborhood of 30%. That’s assuming that a pretty large percentage of your battery drain is from your display, because the drain caused by the antenna could be reduced by 80%.

And what’s the downside? Well, as it stands if your buddy catches a Pokémon before you do, it’s gone from the world. With a more aggressive prefetching and caching, you run the risk that more than one player might successfully catch a given Pokémon. But who cares if two people catch the same Pidgey? On the other hand, if a legendary dragon is in the neighborhood, that could be a bigger deal. So I recommend dynamic caching and prefetching based on the sum rarity value of nearby Pokémon. If there’s a Mew around the corner, then by all means drain my battery with constant phone-homes to see if anyone has caught it yet. But eating up two hours of my battery life to catch three Caterpies is atrocious.

Caching Static Data

And some things should always be cached. There’s a Pokéstop right across the street from my house. But I never go there because the internet there is awful and I’ll just be staring at a white disc that doesn’t drop any loot. Pokéstops are static. The only thing about them that ever changes is whether or not they have a lure module attached, and that data is a single boolean fetched long before I get to the stop. There is no good reason to ever force dynamic loading of Pokéstop data in the areas I spend most of my time.

More Sensible Sensors

One of my biggest pet peeves with the gameplay side of the game is that it has to be open and in the foreground to do anything. That means that I never have the experience of reading a webpage or listening to my music and then being alerted that there’s a Pokémon nearby, which I feel would definitely add to the game’s immersive appeal. It also means that, even though my pedometer app says I’ve walked 2 km this morning, my egg didn’t hatch because I didn’t have the app open (because I couldn’t log in). Let’s keep that pedometer app in mind a second. I have an app that constantly, every minute of every day, tracks how far I’ve gone and how many steps I’ve taken. And it consumes almost no battery. It doesn’t even show up on my list of battery consumers. But it’s very nearly as precise as any purpose-built pedometer. So why can’t Pokémon GO do that? I can’t reach into its internals and find out, but based on everything else I see I assume it’s because Niantic applies this same always-on mindset to their sensor and GPS usage. The truth is that when your user is standing still there is no need to be continuously polling the GPS. But you can see Pokémon GO doing exactly that by the location pin in your notification bar. What’s more, Android likes to batch GPS requests, and good-natured location-aware services will often just wait until the system makes the next GPS poll instead of pushing their own poll. That means that every time Pokémon GO polls the GPS, it may also be waking up every other location aware service on your phone and causing them to use more battery as well.

In addition to the local benefits from reducing coupling to remote servers, the server load on Niantic’s end could be dramatically decreased by this kind of prefetching and caching. The end result would not only be an improved player experience, but also cost savings (and face savings) to the publisher. I would recommend having exclusively asynchronous connections, not forcing the user to wait on data. I would also recommend allowing offline access to cached static data with background data refreshes between server and app, and aggressively prefetching data based on the user’s current location, heading and speed. And speaking of location, heading and speed, Niantic needs to take a cue from other location-aware apps and tone things down a notch. With improved gameplay performance, improved robustness, and dramatically reduced battery drain, Pokémon GO might be able to live through the slump it will undoubtedly see at the end of the summer.