Labs: iTorque2D vs. Cocos2D Performance
Over the past few days I have been determining the performance of iTorque2D, the game engine we are currently using to build our games. Our criteria for picking a game engine was broad, and we knew when we chose iTorque2D that performance would very possibly be an issue.
In order for me to correctly determine the potential performance on the platform, I created basic tests in both iTorque2D and Cocos2D. I chose Cocos2D because it is a good bar for performance on the iOS platform. They also already have some performance tests which are quite useful.
To put it plainly, Cocos2D blows iTorque2D out of the water when it comes to graphics performance. These tests were run on a first generation iPad.
|Number of sprites||30||100||300||1000||1500|
|iTorque2D 1.4.1 FPS||60||1||N/A||N/A||N/A|
|Cocos2d v1.0.0-rc FPS||60||60||54||20||15|
You can get the project files here: (iTorque2D) and (Cocos2D). The iTorque2D files will most likely not compile and run as expected, because there are bugs with the sourceRect feature, explained in more detail after the article. I have also been fixing and modifying numerous issues with iT2D as I come across them. The Cocos2D project will most likely run as expected.
The project loads a scene, initializes 10 sprite sheets, creates X number of sprites, and then bounces them around, pong-style. In Cocos2D it uses Zwoptex-exported plist files to determine the source rects. They are being rendered with CCBatchNodes. In iTorque2D the sprite sheet coords are currently manually entered into the test file, and a bunch of sprites are generated dynamically. The idea was to create a more realistic number of sprite sheets and see how many sprites can be created with the sheets.
So why such a huge discrepancy? Batch calls.
This is a screenshot of Instruments running with a 100 sprites test. You’ll notice that the Batch and Platform calls in iTorque2D are about 10x the number in Cocos2D. This makes sense, since each StaticSprite in iTorque2D is its own batch call, which is why performance suffers so drastically. In Cocos2D the batch calls are perfectly aligned with the number of sprite sheets (and one extra for the fps meter in the lower right). The number of batch calls in Cocos2D stays at the number of CCBatchNodes, while iTorque2D’s batch calls continue increasing for each t2dStaticSprite. Batch calls are the bottleneck on OpenGL ES devices, and so this causes a quick and drastic performance drop in iTorque2D.
I also ran some of these tests on an iPad 2, but the performance of an iPad 2 was easily 3x that of an iPad in my testing. This didn’t provide much data beyond the cool factor of how fast an iPad 2 is. One key finding is the visibility of the CCBatchNodes as layers. All gray ones are on top, followed by yellow ones, etc. I have yet to learn if this is part of the tradeoffs of an OpenGL batch call, or just a drawback of using CCBatchNode (if you know, please tell me).
This is by no means an exhaustive test, and I will most likely create more tests down the road. But for right now these tests confirm what I expected to be the performance bottleneck for iTorque2D. Other Instruments tests have shown me that the iTorque2D engine is:
- Rather stable.
- Has no major CPU hogs. In our game the CPU is quite free, even with two physics engines and a good number of sprites.
- No (major) memory leaks (580 bytes at the very beginning, leaked once)
- A decent memory footprint. Graphics are the main memory hog.
- There is a stutter, every couple of seconds that I will have to look into.
While a significantly low frame rate once you hit a certain number of sprites is pretty bad, I’m glad that it was the problem I was expecting to have, versus a crazier problem I didn’t expect. Garage Games is aware of this issue, because they have what looks like a barely-implemented t2dBatchNode class mentioned in the source code. This is the direction that I will be moving in, implementing batch calling in iTorque2D, and using these tests as a foundation with which to improve performance to a level that will hopefully be near Cocos2D.
I look forward to any comments or ideas related to improving these tests, or pointing out mistakes that I may have made. This test is just my beginning into the wide world of OpenGL ES programming.
SourceRect Issues with iTorque2D
There are issues with the sourceRect feature of iTorque2D that are mentioned here. I have implemented a fix, based on the fix mentioned in the post. The fix revolves around the mSrcRect being a RectF ( a float rect), and says to change certain lines to be a RectI(an int rect). These are not all the changes necessary, it is important to completely replace the RectF implementation with RectI, or you will get some strange data saved for sourceRect params when it writes out the int as a float. This will look like sourceRect = “1231231231223 12336543234 454435463 32454565″ instead of sourceRect=”0 0 100 100″. Everything looks good on the surface, but things behave inconsistently when you set a sourceRect in code, which is what I was doing in my TestSpritesBehavior.