Dreadful Display Object Performance. What Can I Do?

I’m really concerned by the performance I’m getting on my iPhone 4. I have a *very* simple game, but it has a hard time maintaining even 30FPS. On average, it runs closer to 15-20FPS.

I do have a large number of display objects in the scene (around 85). 50 of those display objects have a simple script attached to them that gradually fades them in and out over time. So on each frame, I’m looping over my table of those 50 objects and adjusting their alpha value slightly.

I’ve tried reducing the number of fading objects, and even with 10 fading objects the performance is still awful.

What are my options here? Would texture atlasing help performance at all? I’m running out of ideas…

Here are the relevant chunks of code in case that helps:

main.lua

local previousTime = system.getTimer()  
  
local function Update( event )  
 local currentTime = system.getTimer()  
 local dt = currentTime - previousTime  
 previousTime = currentTime  
  
 background.Update( dt )  
  
 moon01:Update( dt )  
  
 cloud01:Update( dt )  
 cloud02:Update( dt )  
 cloud03:Update( dt )  
end  

background.lua

background.Update = function( dt )  
 local overlays = background.overlays  
  
 for i = 1, #overlays do  
 overlays[i]:Update( dt )  
 end  
end  

overlay.lua

[code]
function overlay:Update( dt )
local getTimer = system.getTimer
local texture = self.texture

if self.delay > 0 then
self.delay = self.delay - dt
if self.delay <= 0 then self.startingTime = getTimer() end
return
end

if self.fadingIn then
local newAlpha = ( getTimer() - self.startingTime ) / ( self.transitionTime )

if newAlpha > 1 then
texture.alpha = 1
self.startingTime = system.getTimer()
self.delay = math.random( 0, 10000 )
self.fadingIn = false
else
texture.alpha = newAlpha
end
else
local newAlpha = 1 - (( getTimer() - self.startingTime ) / ( self.transitionTime ))

if newAlpha < 0 then
texture.alpha = 0
self.startingTime = getTimer()
self.delay = math.random( 0, 10000 )
self.fadingIn = true
else
texture.alpha = newAlpha
end
end
end
[/code] [import]uid: 82003 topic_id: 20749 reply_id: 320749[/import]

Hi!
You could definitly have 80 displayObjects on the scene without causing your iphone 4 to slow down.
It all depends on how large the objects are and what you are doing with them.
I wouldnt recommend changing opacity/alpha due its very perfomance demanding.

So If you use smaller images and replace the opacity animation with something else, maybe scaling-down, then it should run smoothly.

[import]uid: 103182 topic_id: 20749 reply_id: 81540[/import]

do you have to do it in enterframe? You might find it works better with transitions as these wont hold up display updates. You could just use onComplete to randomise the next fade and start a new transition. [import]uid: 8872 topic_id: 20749 reply_id: 81564[/import]

Hmm, I can’t say definitively what the issue is, but I have a scene that can have 60+ objects comprised of several layered images and masks, with display properties that change every frame, and I’m getting around 60 fps. I’m using an object oriented approach so each object does stuff on its enterframe, rather than iterating through a list of objects and calling their update function manually. Simply iterating through that many objects every frame sounds like it can be eating up a lot of time. I bought and used the Corona Profiler (http://www.mydevelopersgames.com/site/) and found a lot of problem areas in my code, which I was able to restructure to improve my framerate. [import]uid: 120 topic_id: 20749 reply_id: 81581[/import]

Thanks so much for the responses so far!

@marceloblanco, I didn’t realize that adjusting each object’s alpha value comes with a performance hit. But I did just try animating the scale rather than the alpha and the framerate was still in the 20s on my iPhone :frowning: I’ll see if I can try reducing the size of the textures…

@kam187, At first I had all of the fades implemented using transition.to. But I was getting the bad framerate and I read somewhere on the forums that transition.to impacts performance more than enterframe. I spent some time moving everything over to enterframe, and I haven’t noticed much of a difference :frowning:

@bryan.vaccaro, I hadn’t thought about attaching an enterframe event to each object rather than looping through everything manually. I bought the Corona Profiler, and it’s definitely complaining about the areas where I’m manually looping through all of my display objects. I’ll try using event listeners for each of my objects instead. Thanks for the suggestion! [import]uid: 82003 topic_id: 20749 reply_id: 81586[/import]

if they all fade in and out at same time you could put all in a group then fade the group in and out [import]uid: 7911 topic_id: 20749 reply_id: 81592[/import]

Ugh, this is getting awfully frustrating :slight_smile:

I changed my code so that each fading object has its own enterFrame listener (thanks bryan.vaccaro for helping me out in the other thread I posted!), but it’s still running at around 20FPS on my iPhone. The Corona Profiler was happier with my code, though.

I then tried removing the enterFrame listeners on *all* of my objects. I just wanted to see how fast the game would run with 80 static objects displayed on screen – no fading, scaling, or any other kind of animation. The game *still* ran at 20FPS. My frame rate only goes up when I start removing display objects from the scene.

I’m not sure what I can try next :frowning: [import]uid: 82003 topic_id: 20749 reply_id: 81748[/import]

I’ve done a couple mobile projects in Unity, and one of the performance bottlenecks is the number of draw calls. Could that be the problem here?

Unity automatically batches draw calls that share the same material / texture atlas. If I stick all of my textures into an atlas using TexturePacker and reference them using the spritesheet API, will that improve performance? [import]uid: 82003 topic_id: 20749 reply_id: 81751[/import]

Which model iPhone are you using?

One thing that was killing my performance was lines like this:

newObject.x = newObject.x + math.random(1,4)  
newObject.y = newObject.y + math.random(1,4)  

et c.

Accessing the properties of an object is really slow so it should be done as few times as possible. In my case, I stored the X and Y as variables and only set newObject.x and .y once per enterFrame… it probably doubled my framerate.

That said, I applied your alpha animating code in the other thread to some objects in my game and spawned 60-80 instances, all moving, rotating, and changing alpha with no hiccups. Try checking with Profiler in memory timeline mode and see if there’s anything weird going on there, too. [import]uid: 120 topic_id: 20749 reply_id: 81755[/import]

Good suggestions! I’ll take a look and see where I can optimize my code to reduce the number of times I’m accessing an object’s properties.

Are you using texture atlases and the spritesheet API in your game? Has that improved performance? [import]uid: 82003 topic_id: 20749 reply_id: 81756[/import]

just a thought, have you optimized your image files [import]uid: 7911 topic_id: 20749 reply_id: 81935[/import]

How do you optimize your image files?

I guess if I have to ask that means I haven’t optimized them :slight_smile: [import]uid: 82003 topic_id: 20749 reply_id: 81939[/import]

on Mac I use imageOptim
just run the app then drag image files to the window
on pc idk but sure there’s something [import]uid: 7911 topic_id: 20749 reply_id: 81943[/import]

here’s a link
http://imageoptim.pornel.net/ [import]uid: 7911 topic_id: 20749 reply_id: 81946[/import]

Oh, great! I’ll run my images through that and see what happens :slight_smile: Thanks! [import]uid: 82003 topic_id: 20749 reply_id: 81948[/import]

are you using 80 different images or are they the same? and what’s the size of the images, in width and height?

the bigger images you use, the more memory and processing power you’ll need.
i’m guessing that either your images are too big. [import]uid: 103182 topic_id: 20749 reply_id: 81960[/import]

80 different images. Most of them are 200x100 (100x50 for lower resolution devices).

If each image is its own draw call, wouldn’t I see a significant performance improvement if I atlas them and use the spritesheet API? I might take a stab at that today, but getting the dynamic content scaling working with spritesheets worries me :slight_smile: [import]uid: 82003 topic_id: 20749 reply_id: 81963[/import]

@bdjones I’m not currently using spritesheets because of some issues I had with them (something about masking limitations). In the test I ran with your alpha animating code, I was animating 60-80 displayGroups that each contained 4 or 5 images in them with dimensions ranging from 96x96 to 128x128. So, that’s quite a bit of stuff moving around. Performance was noticeably better when I was using spritesheets, so hopefully I can work around the problem and optimize further.
@jstrahan Does optimizing pngs have a real impact on memory usage/performance? I thought the files were all compressed server side when building the app anyway? [import]uid: 120 topic_id: 20749 reply_id: 81964[/import]

@bdjones seems like using 80 different images may mean the difference between my code and yours… how much texture memory is that using? Spritesheets should help a ton, keep in mind that a 200x100 px image takes up as much memory as a 256x128 image. [import]uid: 120 topic_id: 20749 reply_id: 81966[/import]

I have no sense of how big or small these numbers are, but here’s the amount of texture memory that I’m using (based on the code here):

MemUsage: 124.8115234375
TexMem: 133.070848

This is without spritesheets and without optimized images.

What guideline do you use to determine how much texture memory usage is too much? [import]uid: 82003 topic_id: 20749 reply_id: 81984[/import]