New image sheets / image group speed tests and results.

NOTE: This was originally posted in the Lime subforum, as people had expressed concern regarding performance issues in Corona. The following is very specifically about graphically intensive tasks - in this particular case about using tile sets to draw tile maps.
Also relevant is that the following refers to features only available to subscribers.

I have spent the last couple of days messing around with image sheets and image groups, and it is impossible to be 100% accurate regarding performance gains due to the bugs that prevent me doing direct code comparisions, but my findings are as follows (in each case, the differences between A and B are in italics):

The first test should have been a direct comparison between old and new methods, but was prevented by the fact there is a crashing bug when you combine new display groups, :setFrame and making sprites visible / invisible.

Comparison 1:
A) Old sprites, .currentFrame, old display group, visible / invisible toggle
B) Image sheet, new sprites, :setFrame(), old display group, visible / invisible toggle

Results:
A) 26 fps.
B) 26 fps. Interesting…

The second comparision came about as a result of me initially thinking the bug was caused purely by the :setFrame(), so I simply removed it, while using as many other new features as possible.

Comparison 2:
A) Old sprites, old display group, visible / invisible toggle
B) Image sheet, new sprites, new image group, visible / invisible toggle

Results:
A) 28 fps.
B) 60 fps. Note it could well be higher but of course the settings limit it to 60fps max.

The third comparison was to find a way to compare between the new methods but where the only variable was using old display groups or new image groups. To achieve this, due to the previously stated bug, instead of making sprites visible or invisible, I set ‘invisible’ ones to a frame that contained a tile with an alpha making it totally transparent.

Comparison 3:
A) Image sheet, new sprites, old display group, :setFrame(), blank tiles
B) Image sheet, new sprites, new image group, :setFrame(), blank tiles

Results:
A) 18 fps.
B) 45 fps.

The final comparison is just to test the difference between making a sprite visible and invisible, or using a blank, transparent tile - hopefully this will let me make a prediction about what sort of framerates might be possible when combining all the new features.

Comparison 4:
A) Old sprites, .currentFrame, old display group, visible / invisible toggle
B) Old sprites, .currentFrame, old display group, blank tile

Results:
A) 26 fps.
B) 18 fps.

Notes:

  • My tests are done in code for a platformer game, and does include collision code.
  • They were run on an iPad 2 in landscape format, with each layer of parallax being fullscreen using tiles of 32x32 pixels. A single layer uses 33x25 tiles (one more than you’d expect to account for offsets), or 825 sprites.
  • The demo contains 8 layers of this, for a grand total of 6600 sprites in the level graphics.
  • Not every layer is solidly packed with sprites. Each layer contains ‘holes’ where you can see the layers behind. This is because I was using a test level I knocked up quickly, which would emulate more realistically what I’d do in a game. It also is useful in that it shows the speed differences between hiding a sprite, or drawing a transparent one instead.
  • Every tile is redrawn every frame. This allows for per-tile animation without any overhead. I am a fan of this method for simplicity, and because you almost always know your worst-case scenario, but it is not the only way, naturally. Possibly I could optimise the code further by making the tiles themselves never animate, and only redrawing sprites when they move offscreen and wrap them to the other side. However, for the effort involved and the limitations imposed, I feel it is not worth-while.
  • I measured the FPS by finding the spot in the map with the lowest FPS and idling there a few seconds to let things stabilise, although for tests using blank tiles, realistically any location is as good as another. The FPS code itself is a library taken from this very site.

Conclusions:
Image sheets alone didn’t actually provide a speed benefit, something which concerned me enough to double and triple check my numbers. But upon re-reading John’s blog post, nowhere does it suggest there are performance gains from using image sheets, and I realised this makes sense. The benefits come from fewer disk reads, and simplification of the APIs. It does come at the cost of the additional complexities of making and defining texture atlases, however.

But image groups? They are exactly what is needed for performance gains!

My conclusion would be that although I am unable as yet to fully test and exploit the new features due to a bug, what I have seen is proving to be very, very impressive! I am more than happy eating my words about the potential speed gains Ansca could and did achieve (based as it was on the fact I already felt Corona is very quick all things considered), and it makes me happy for us all and the future of Corona!

But! If you are going to go to the trouble of making texture atlases, DO plan ahead for using image groups, when the final bugs are ironed out - you will be amazed :slight_smile:

[EDIT]I nowhere mention the benefits of culling used with the new commands. The reason is simple, I don’t use it nor need it, but that may well have a large effect on Tiled things, which hopefully someone else can look into. [import]uid: 46639 topic_id: 24600 reply_id: 324600[/import]

This is very detailed, I will pass the link on to the rest of the team.

Thanks!

Peach :slight_smile: [import]uid: 52491 topic_id: 24600 reply_id: 99728[/import]

Peach, regarding the bug, I was not able to do a simple code example, but I do have a stripped down version of the entire demo, which I am willing to send you guys to help quash the bug, but I am not sure how best to go about that. [import]uid: 46639 topic_id: 24600 reply_id: 99799[/import]

@rakoonic, great data!

Image groups start to give you a win when you have lots of image objects (or sprite objects) on screen.

Under the hood, we do a separate glDrawArrays() call for each display object. This is a well-known performance bottleneck in OpenGL, so we introduced image groups as a way to optimize that away. [import]uid: 26 topic_id: 24600 reply_id: 99833[/import]

Walter - I figured it was something like this, but rather than just say it is faster, I figured I’d do some real-world tests, because people were asking for this sort of thing. The results are awesome, so thanks a lot for the efforts (now just kill that bug I found and I can actually use it in a game, hint hint :smiley: ). [import]uid: 46639 topic_id: 24600 reply_id: 99837[/import]

Hey again,

So were you able to submit it? If not, we have a link in the top right which takes you to a form - from there you can enter info and add the zip file :slight_smile:

Peach [import]uid: 52491 topic_id: 24600 reply_id: 100040[/import]