Cocos2d-x vs Starling performance benchmarks

Hi,
I did performance comparison between cocos2d-x and Starling(the GPU accelerated flash AS3 engine). Project files are attached at the end of this message.

Here are the numbers:

1 sprite repeatedly rendered on the screen.
Test hardware: iPod touch 4

***Case 1: **+
SpritesStirling FPS ——— Cocos2d-x FPS
10 ————— 60 ————— 60
100 ————— 60 ————— 60
200 ————— 60 ————— 60
300 ————— 60 ————— 60
400 ————— 60 ————— 59
500 ————— 60 ————— 47
700 ————— 49 ————— 36
1000 ————— 36 ————— 25
2000 ————— 19 ————— 13
3000 ————— 13 ————— 9
When there is no scale or opacity change, Starling is faster than coco2d-x
***Case 2: **+
SpritesStirling FPS ——— Cocos2d-x FPS
10 ————— 60 ————— 60
100 ————— 60 ————— 60
200 ————— 44 ————— 60
300 ————— 30 ————— 60
400 ————— 23 ————— 59
500 ————— 19 ————— 47
700 ————— 13 ————— 35
1000 ————— 10 ————— 26
2000 ————— 5 ————— 13
3000 ————— N/A ————— 9

In case if both scaling and opacity are enabled cocos2d-x is beating Starling pretty badly!

My question:
Why starling (which is AS3 based) is performing better than cocos2d-x in case 1 ?

DaisyMark cocos2d-x port:

*DaisyMark starling AS3 code: (flash builder project)*
http://dl.dropbox.com/u/11258564/DaisyMark.zip

I don’t know Starling specifically but this seems like an issue with the number of draw calls being made. Not knowing the details of Starling it’s possibly performing some behind the scenes batching of your sprites where it can draw many in a single draw call.

In Cocos2d-x by default every CCSprite gets an individual draw call. If you want batching behaviour you should look into CCSpriteBatchNode, this takes over drawing of it’s children (who must all be CCSprites) and draws everything in one call. This tends to be much better for performance. All the sprites in a batch node need to use the same texture (actually the texture is a property of the batch node). I think if you were to change your Cocos2d-x test to use this then it would consistently beat Starling.

I hope that’s helpful to you.

Fakhir Shaheen, I've read your code.Stuart McGaw is right, you should use CCSpriteBatchNode to reduce the draw call, instead of one sprite for each class Particle, which will cause lots of draw calls.

I’ve modified the Particle class’s constructor to use CCSpriteBatchNode:

@
Particle(cocos2d::CCNode * parent){
if(batch == NULL){
CCLOG (“Initializing sprite batch”);
cocos2d::CCSpriteFrameCache::sharedSpriteFrameCache()>addSpriteFramesWithFile;
batch = cocos2d::CCSpriteBatchNode::create;
parent
>addChild(batch);
}
sprite = cocos2d::CCSprite::createWithSpriteFrameName(“daisy.png”);
}
@

Absolutely NO performance difference. It appears that CCSprite uses batching by default. Is the above code right?

The numbers in the lower left corner of the screen along with FPS, they show number of children on the screen or number of draw calls?

Updated cocos2d-x project:

Well, I’ve sent you a pull request https://github.com/fakhirsh/DaisyMark-cc2dx/pull/1 The CCBatchNode hasn’t been used correctly, as I wrote in the pull request.
To be honest, even if Ricardo Quesada improved the API set of batch node in v2.x, it’s still a bit confusing to users.

In the previous code, the error points of using CCBatchNode are:
# CCBatchNode is created from daisy-texture.png, while sprites are created from daisy.png. There’s no relationship between sprites and batchNode in your code.
# You added both batchNode and sprites as children of parent node, while the correct usage is to
## parent~~>addChild
## batchNode~~>addChild(sprite)
* NOTE: This line breaks the batchNode optimisation: parent->addChild(sprite)

I increased the particle number from 700 to 2000, batchNode speed up the rendering correctly on my ipad2. You can have a try.

And you’ve noticed the numbers in the bottom-left corners. Their meanings are:

1          <--- How many times of draw calls in one frame
0.016      <--- How long (in seconds) per frame
59.8       <--- FPS

The draw call is 1 if you use batch node properly here, while it will equal to DaisyTest::numParticles if the batch node doesn’t take its job.

OK, I built a 2dx version of DaisyMark, which is attached in this post. Comparing to the Adobe AIR version in your dropbox, the performances on my mobiel phone are
* Device: Galaxy Nexus
* Android Version: 4.2.1
* Particle number: 1000
* Using test case 1, scale and opacity are disabled
* DaisyMark with Adobe AIR and starling: 12~14 FPS,
* DaisyMark with Cocos2d-x v2.1.1: 32~34 FPS

Hi,

Sorry I couldn’t pull your request, i am new to git :slight_smile:

I just modified the code. Now it is using batching properly:
@
batch->addChild(p->sprite);
@

Test device: iPod touch 4

On the device there is now only 1 draw call even for 3000 sprites. NO significant performance gain at all (just an increase of few FPS). It is still slower than Daisy Mark .

PS: Did you compile starling AIR version DaisyMark using “Flash builder —> Project —> export release build (AppStore)” ?

Updated code:

Fakhir Shaheen wrote:

Sorry I couldn’t pull your request, i am new to git :slight_smile:

Well, use my repo directly: https://github.com/walzer/DaisyMark-cc2dx/tree/multi-platform-cpp-and-js
I also rewrote a version in cocos2d js, it still have higher performance than starling on Galaxy Nexus.
If you want to build it, just put cocos2d-x/project/ directory, cocos2d-x/project/DaisyMark-cocos2djs and cocos2d-x/project/DaisyMark-cocos2dx
You usage still seems to be incorrect. You may use a big texture in particle.