We knew from the very beginning that, having a binary this big is not ideal. Some of the common problems with having big binaries are:
- The time taken for end users to download and start using the app, linearly increases with size of binary.
- People just don't sit around and watch the app being downloaded, they browse/download other apps, do other stuff, if the download takes longer we might end up getting a download but losing a user.
- Not to mention the space that it takes up on the device. Might not be such a big problem for the iPads but certainly a concern for iPhones.
- Time taken to distribute the alpha/beta/prod builds increases with the size of binary.
These are just a few points but the list can go on and on. After a few releases, we started actively looking for ways to reduce the size of our binary. We evaluated numerous options and finally managed to reduce the binary size to around 39MB only!
How Do They Do It!
This post is a developer log of all the things we did to actually get us such great savings on the binary size!
NOTE: Detailed examples of how to do each of the following steps will be covered in subsequent posts.
Identify Biggest Assets In The App
- This one is by far the easiest step of all, we can easily do a file system sort by size descending, on all the files that get shipped into your application.
- No surprises here, as expected, biggest chunk comes from
- Image files
- Music files
- Sound files
Converting 24bit PNG's to 8bit PNG's
- All images in our application were in PNG format.
- One option was to convert them to JPEG to reduce the size, but I was not too keen on that.
- Digging a bit deeper we realised that all our images were PNG 24 bit.
- We changed all of them to PNG 8 bit
- We could not see any huge drop in quality - not that we are any experts on the topic - but for a regular user it didn't make much difference.
- This single step will get you around 70-80% reduction in size of all the image assets in your application. Awesome isn't it!
Converting 8bit PNG's to WebP
- We were still not satisfied with our final binary size, so we went hunting for more optimisations.
- What we stumbled upon was a new image format called WebP from google.
- Its an awesome format, provides lossless and lossy compression for images.
- The lossless compression is a whooping 26% smaller than the PNG's.
- To use WebP in your iOS app you will need to integrate iOS-WebP or a similar SDK.
- This added awesomeness, did come with some headaches.
- The performance of the game took a bit of a hit, because of added overhead of decoding WebP images
- This was more apparent when bigger images needed to be decoded for e.g. the backgrounds of scene.
- To get around this problem we eagerly decoded some of the most commonly used WebP images into PNG's on first launch of the game.
- And from within the game we use these decoded PNG images. This solved the performance issue to a great extent.
I know you are itching to look at the code of how we did all this, but please bare with me till the subsequent posts to see the details of each step.
Convert All Sounds and Music files from WAV (or any other format to) AAC Format
- WAV files are huge, don't use them period!
- Converting them to AAC format gave us big savings around 70-80% on each file.
Reducing bit rate of AAC Voices to 32K
- We noticed that reducing the bit rate of all voices (yep! we have voice overs in our app) to around 32K didn't impact the quality much (Note that we only reduced the bitrate of Voices not the background music).
- They felt the same when they were played back - again no experts on the subject - but for a normal user it didn't seem to make much difference.
- This give us another 70-80% reduction in size per voice file!
Seem like a lot of work? But the end result is equally rewarding, we did manage to reduce the size of our binary to be just under 40MB!
We started from ~108MB and came down to ~39MB, its like more than 63% reduction in the final size!
As mentioned early, watch out for the next set of posts where I will explain in detail on how to perform each of the above steps with code examples. Till then, keep rocking!