App icon for Candy Crush Saga

Candy Crush Saga

July 17, 2023
Candy Crush Saga Gameplay
Candy Crush Saga Gameplay

This is the One Piece of mobile games. There are over 14.5k levels in Candy Crush Saga across 968 "episodes". Every single "level" has its own .txt file, which allows us to examine one of the most extreme differences in file size between iOS and Android.

Game Structure

The majority of the code for Candy Crush Saga is located in the /res_output directory for both iOS and Android. Here, you can find a variety of directories where animations, textures, sounds, levels, and more are stored and encoded.

If you’re comparing sizes across iOS and Android, the Install Size for iOS and Uncompressed Size for Android are mostly similar across the different directories - /res_output/tex/candy_hd.webp is 823 KB on iOS and 781 KB on Android. The biggest difference comes in the “levels” directory.

On both platforms, there are the same ~14,500 .txt files in /res_output/levels. On Android, the levels take up 27.6 MB of Uncompressed Size. On iOS, these same files take up 57.9 MB - so where’s the difference coming from?

A level file is JSON data describing a specific level. Here’s a JSON snippet for the smallest level in the game episode1level8.txt

{
  "episodeId": 0,
  "gameModeName": "Light up",
  "id_meta": 8,
  "levelDefinitionId_meta": 1640342,
  "levelId": "215741",
  "levelType": [],
  "moveLimit": 12,
  "numberOfColours": 4,
  "protocolVersion": "0.3",
  "qa": false,
  "randomConfig": {
    "mode": "Seed Pool",
    "modeModifier": "Tutorial Only",
    "seedPool": [6]
  },
  "randomSeed": 0,
  "scoreTargets": [10000, 30000, 40000],
  "tileMap": [
    ["000", "000", "000", "000", "000", "000", "000", "000", "000"],
    ["000", "000", "000", "002005026", "002005026", "002005026", "000", "000", "000"],
    ["000", "000", "002", "002003", "002003", "002003", "002", "000", "000"],
    ["000", "002", "002003", "002003", "002003", "002003", "002003", "002", "000"],
    ["000", "002", "002003", "002003", "002003", "002003", "002003", "002", "000"],
    ["000", "002", "002003", "002003", "002003", "002003", "002003", "002", "000"],
    ["000", "000", "002", "002003", "002003", "002003", "002", "000", "000"],
    ["000", "000", "000", "002", "002", "002", "000", "000", "000"],
    ["000", "000", "000", "000", "000", "000", "000", "000", "000"]
  ]
}

On Android, this snippet takes up 919 B (uncompressed). On iOS, this file takes up 4.1 KB, almost 3.5× more space. The reason for the file size difference is due to the file system’s allocation size. On iOS, the minimum file size allocation is 4096 bytes, meaning the smallest a file can be is ~4.1 KB.

In total, Candy Crush has over 20k files under 4KB. For most apps, the minimum file size allocation doesn’t cause significant overhead, but most apps don’t have 40 levels for every day of the year.

Image showing size of the "Code Resources" file in Candy Crush Saga (8.2 MB)
8.2 MB Code Resources file

In addition to there being a minimum file size, every file adds overhead to your code due to code signing. In the `_CodeSignature` folder of your app, there is a plist file called `CodeResources` which contains a mapping of every file name to its code signature.

Potential Optimizations

Candy Crush could cut down on the small file overhead by packing them into an asset catalog. This compiles as a single .car file which solves both the minimum file size and code signing overhead issues. You could then use NSDataAssets to load any resource from the asset catalog. The tradeoff is a slight runtime cost to unpack the files.

A more involved optimization is changing how the levels data is encoded. Looking at the JSON example above, you can see that many of the keys would be duplicated for every level file. Also, many of the values are human-readable when they appear to be enum values.

One potential alternative is to use a more space-efficient binary format like protobuf. This format also has great support for representing repeated values. Another alternative – say if they want to continue using JSON – is to use a proprietary lookup table for repeated values, for example having a file that contains a list of all potential keys and then the level files contain a list of all values. This is similar to how Airbnb handles localization file size and requires the list of values to match the list of keys.

Image Candy Crush Saga has 74.8 MB of binary symbols

While unrelated to the "levels" files, the biggest optimization Candy Crush Saga could make is to strip binary symbols. Candy Crush introduced ~70 MB of binary symbols in v1.249 when they switched to Xcode 14. These symbols are still in the app and can easily be stripped out.

Side note - the Candy Crush Saga wiki is insanely well documented. For fun, we looked up the largest level in the game by file size (`episode608level11`) and the wiki already had that as trivia for the level!!!!
Screenshot of the Candy Crush Saga Wiki saying "this level is the biggest code in game file in reality which has 4,883 bytes."

Sign up for our newsletter 🛸

Never miss a post or product update



2024 © Emerge Tools, Inc. All rights reserved.