Hi all :)
I'm really struggling to keep the performance (FPS) for my game up (esp. on Class 1 devices) and looked through the forum for many hours to find the best tips and tricks as well as best practices for constant high FPS. As it seems, I'm not the only one looking for help regarding performance. So I think we should start to gather latest and greatest knowledge in this thread to help riq (or someone else) update the http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:best_practices accordingly.
This thread is open for all comments, improvements, tips, tricks, help, etc. from anyone that has something to contribute or correct, but...
! PLEASE DO NOT USE IT TO ASK QUESTIONS !
...if it does not "help the thread". ;)
----------------------------------------------------------
P A R A M E T E R S
----------------------------------------------------------
Let's get started by defining some basic parameters.
----- Parameter: Device -----
First of all I'd like to introduce 4 classes of devices. Besides the Simulator there is Class 1 & 2 for iPod and iPhone, as well as Class A for the iPad. This is just to avoid further discussion what device the performance tests refer to. For example: we can simply talk about a Class 2 device then ;)
- Simulator: Xcode + Version
- iPhone- /iPod- /iPad Simulator - Class 1: 1st generation-iPhone-iPod-CPU/GPU
- iPhone (iPhone1,1)
- iPhone 3G (iPhone1,2)
- iPod touch (iPod1,1 + iPod2,1) - Class 2: 2nd generation-iPhone-iPod-CPU/GPU
- iPhone 3GS (iPhone2,1)
- iPod touch (iPod3,1) - Class A: 1st generation iPad CPU/GPU
- iPad (unknown)
-
----- Parameter: Cocos2d version -----
- From my perspective it makes most sense to refer to a "released" version of cocos2d which would be:
"cocos2d for iPhone v0.9.0-beta2" from January 11, 2010 at the moment. I think most of the people that use such a framework want to stick to a supported and well-tested release to have a quite stable basis to build on. I therefore think it's not a good idea to use specific builds of the trunk in the SVN to start collecting facts. If you think otherwise, let me know - we can talk it out ;)
-
----- Parameter: Abstract -----
- Your application's abstract - i.e. use of objects, classes, etc. This is the most complicated parameter to take into account, as it consists of many sub-parameters. If we want to start collecting facts that are comparable, ideally we all should use the same game/code. This is not easilly possible, so I thought of the demos in the project that come with cocos2d but these are mostly good for reference of how-to-use a certain function or class. The performance tests for sprites and particle systems also came to my mind but they are quite special cases, very likely not real-world scenarios we all use in games. So to have something compareable, I think we have two options...
Option 1: We create one or more test scenarios that cover the combined functions we really need (create a pseudo-game?).
Option 2: We post our experiences and include a high-level abstraction of classes and structure used.
As option 1 would be surely great, but more time consuming. For now I suggest we go for option 2 and after we collected enough information, we could create some pseudo-games or even some skeletons for option 1 and future reference.
----------------------------------------------------------
Here is a list of optimizations and best practices I found in the forums and the existing (and slightly outdated) documentation. I've taken the liberty of updating all to my best knowledge and add some things I learned over time. I'm far away from a "pro" so please be kind and help me correcting issues/typos/etc. by posting in this thread. The list is also far from complete, but it is a "start" and I want to maintain it so we all have a good reference. :)
----------------------------------------------------------
O P T I M I Z A T I O N S
----------------------------------------------------------
- [NON-THUMB] Non-thumb code:
- Should be OFF by default for new projects
- To double check the setting follow these steps:
- Right click your target in Xcode
- Select "Get Info"
- Select the "Build" tab
- In the search field "Search in Build Settings" enter: thumb
- Make sure the checkbox for the setting "Compile for Thumb" is unchecked
Notes...
- Thumb code is MUCH slower than non-thumb code - [FAST-DIRECTOR] Fast director:
- Gives you best performance, but worst battery life
- Do the follwing call it in AppDelegate
-[CCDirector setDirectorType:CCDirectorTypeMainLoop];
Notes...
- Fast director doesn’t wait for the vsync
- It might be MUCH faster or slightly faster than the normal director - [USE-ATLAS] Use of atlas:
- Whenever possible, use a texture atlas. In detail this means:
- Use a CCSpriteSheet instead of many CCSprite instances
- Use a CCBitmapFontAtlas or CCLabelAtlas instead of CCLabel
- Use a CCTileMapAtlas to render tiles instead of using many sprites
Notes...
- The Atlas versions of these objects provide faster rendering at the expense of code and art complexity. The Atlas versions utilize an AtlasManager that keeps one large image with multiple frames, and the individual Atlas object refers to a frame of that larger image. This saves on texture counts and accelerates OpenGL ES calls.
- Atlas = a book of illustrations or diagrams. In this context it means you have one big image loaded into an opengl texture which actually holds a series of smaller images. As opposed to all the smaller images each loaded in to their own texture. - [ADJUSTED-BIT-TEXTURE] 16 bit / 4 bit textures
- Do the follwing call before instanciating a CCSprite, CCTileMapAtlas, CCSpriteSheet etc. Generally speaking the lower the bits, the faster the output.
-[CCTexture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA4444]; //16 bit textures
Notes...
- Do a <CMD> doubleclick the constant kTexture2DPixelFormat_RGBA4444 (or similar) in your code to get all constants that are available and so find the best for your case.
- You can restore the texture quality back to you initial setting in the AppDelegate after the creation of the desired object. In other words, you can set it for every instance of an class you use. To get the highest quality use 32 bit textures by calling:
-[CCTexture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA8888]; - [PVRTC-TEXTURE] 4 bit / 2 bit textures
- Lowest quality, best performance:
- CCSprite *sprite = [CCSprite spriteWithFile: @"sprite.pvr"];
----------------------------------------------------------
To sum up: I suggest we use this thread to post experiences based on what we have - so we all can learn. Let's stick to these parameters listed above and create some scenarios including results for the performance under the conditions stated. I created a small template here to get us all started.
TEMPLATE - COPY FROM HERE:
----------------------------------------------------------
Project: ...
Device / performance: ...
Cocos2d version: ...
Abstract:
* ...
* ...
* ...
Optimizations:
* ...
* ...
* ...
----------------------------------------------------------
Best regards,
Markus
PS: Some links...
* iPhone/iPod model number sources: http://www.trejan.com/projects/ipod/
* http://www.cocos2d-iphone.org/wiki/doku.php/perf_test:0_9_0_beta
* http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:best_practices