Mobile Load Times and Installed Package Size
Document Summary: Common methods to help reduce application load time and final install size for mobile applications.
Document Changelog: Initial creation
This page lists some common methods used to help determine and reduce your application load time and install size.
Shader compilation is often a large source of startup times on mobile platforms. Generally it is unacceptable to pay this cost on the fly during gameplay, as the compilation time will be noticeable as hitches in framerate. To avoid hitching the Unreal engine will ‘warm’ most shaders at startup time by precompiling and rendering with them to let the system complete all necessary compilation and shader patching steps.
At the moment mobile devices do not provide a facility to save precompiled/warmed shaders for direct binary loading later.
Shaders on mobile platforms in UE3 are distinguished by their unique shader key. Please see the writeup contained within MobileMaterialReference
for a description of this implementation. Reducing the number of shader keys is not a simple matter of reducing the total material count in your application, as materials can produce a varying number of keys based on a the specific material settings.
Reducing Shader Keys
Mobile Shader Analyzer
tool can help assess how many shader keys your application is generating, what materials they were generated from, and how to alter your materials to reduce them. Refer to the link above for information on the usage of this tool.
As mentioned in the documentation for the MobileShaderAnalyzer
, often materials will iterate multiple versions of some settings since the engine does not know how they will be used. By explicitly informing the engine of your intention with these materials, you can remove many of the iterated versions from your application:
- Skinning. If you see both skinned and non-skinned iterations of shaders that you know will ALWAYS be used on skinned meshes, you can add the material to your application’s DefaultEngine.ini, under the MobileMaterialCookSettings section. Add a ‘+SkinningOnlyMaterials=’ line under this section. During cook only the skinned version of this shader will be created, instantly halving the number of keys created by this material. Example:
- Fog. The engine will generate unfogged and fogged versions of shaders if fogging is enabled for your title, rendering using the unfogged shader dynamically when possible for performance reasons. If your application can afford the performance hit of always using the fogged version of the shader, you can disable this shader iteration by setting bMobileMinimizeFogShaders=true under the [SystemSettings] section in your application’s DefaultSystemSettings.ini
- Particle settings. There are many particle settings that force iteration of an on/off state within the shaders. If you see toggling of any key settings that you aren’t making use of, disable that feature in the material.
Material Instance Constants
An excellent way to minimize shader key creation is to make use of master materials and material instance constants (MICs) as much as possible. Altering MICs in a child material will generally not add any new permutations to the shader keys created from the master material. Authoring your content from the start with master materials is a good way to avoid an explosion in shader keys later in the project. See the MaterialInstanceConstant
page for more information.
Additional Shader Keys Considerations
Shader groups do not help eliminate shader keys, but can be of use by deferring subsets of key warming to other points within the application. The most common example is map loading. You can quickly create a shader group for each level in your app, the cooker will then add all keys for that map to its own shader group, and automatically warm these keys upon load of the level. This will raise your map load times by some amount, but generally lower your overall application loading time significantly.
Per-map shader groups are created through the Engine.ini file under the MobileShaderGroups section like so:
Shaders referenced by the MyMapName map will be added a “MyGroup” shader group, and when you load the map, those shaders will be compiled and warmed.
You can also create shader groups dynamically from your game cooker helper (if you have written one), like the following:
During the game, when you need those shaders compiled, just call
You will want to do this compilation when you have a load screen up or some other static UI so than hitches aren’t visible.
Note that there may be instances where some shader keys are not automatically warmed by the engine, generally the case if 3rd party software is tied into the engine rendering pipeline. You can manually add keys to be warmed at startup by including them within your DefaultEngine.ini file as such:
Boot Time Profiling
Refer to ProfilingBasics
for tips on profiling boot times.
The following sections discuss tools and methods that you can use to help identify and reduce the overall size of your final application package.
IPA Viewer (iOS)
For iOS devices your final executable package is compiled to a single .ipa package to be deployed to the device. The IPAExamine.exe program, located within your UE3/UDK Binaries folder is a command line application used to report on the overall size breakdown of the various files contained within your IPA.
Detailed help on the tool can be found by typing
On the command line.
The most simple usage is to run
IPAExamine <full path to your ipa file>
which will list the contents of the IPA, sorted by extension, with a summary table detailing the size breakdown of each extension type. Often this step alone is enough to point you toward what aspects of your data can be targeted for overall size reduction.
Note that you can detect if shader is warmed at runtime by enabling the MobileFlashRedForUncachedShaders boolean in your system setting ini.
Examining Cooked Data
Once you have identified the areas of your install package to target for reduction, you will likely want to dive deeper into that content to figure out what specific assets are most to blame. Often the largest contributors will be mesh or texture data. The following tools will help determine if this is the case, and dive deeper into each:
To examine the contents of your cooked packages (.xxx files), you can use the PkgInfo commandlet, as detailed in the CommandletList
For example, the output of the command:
Gamename.exe PkgInfo <path to package> -exports –simple –platform=<platform> > myfile.txt
Can be quickly imported into Excel for deeper analysis of the package contents.
If you are unsure of why a certain asset was brought into the package, the Find Asset Referencers Commandlet
, or ‘List Objects that reference this object’ from UnrealEd (making sure ALL packages are loaded first) should provde that information.
Mine Cooked Packages
Another useful tool is the MineCookedPackages
commandlet, used to populate a SQL DB with data on most assets cooked for the build. Detailed instructions can be found on the wiki page linked above.
Mine TFC Data
The Mine Cooked Packages commandlet is extremely powerful, but does not currently take into account editor set LODBias settings on textures, as well as any changes made to the textures due to the texture group settings in your DefaultSystemSettings.ini file (per-device settings are taken into account at runtime, while the ‘base’ settings are used during cook).
If the setting MinTextureResidentMipCount is set to 0 in your engine.ini [TextureStreaming] section (the default for mobile development), then all cooked textures will reside entirely within your TFC files. Knowing this, you can create a log file detailing every texture added to your .tfc files and use it as your final texture manifest. To do this, do a full recook of all your data, passing the –WriteTFCReport flag to the cooker commandlet. This will output a CSV file (TFC_Generation_Report.txt) to your game folder detailing every texture layer cooked, listed by package and size.