Performance Tip: setting isVisible=false is slow! reading display object x/y is slow!

some surprises here… particularly the last point… maybe there’s a better way to do it but some things to be wary of and some conclusions

  • set isVisible=false for offscreen items (initially)
  • cache display object properties (x,y etc) in a “parent” class objevt
  • set isVisible=true when items coords means they should be on screen
  • *don’t* set isVisible=false again for items going back outside the screen bounds

can anyone comment on this?

(I’ve only tested it on the desktop, not the device)

j

[lua]require(“sprite”)

local balls = {}
local world = display.newGroup()

local spriteSheet = sprite.newSpriteSheet(“chuzzle.png”, 46,48)
local spriteSet = sprite.newSpriteSet(spriteSheet, 1,1)

local testball = display.newImage(“chuzzle.png”)

local w = testball.width
local h = testball.height

testball:removeSelf()

local moveSpeed = 0

function init()

local ball = {}

for b=1, 10000, 1 do

ball={}

– ******************************************
– both perform the same here
– ******************************************
– ball.sprite = sprite.newSprite(spriteSet)
ball.sprite = display.newImage(“chuzzle.png”)
– ******************************************

ball.xpos = math.random()*320
ball.ypos = (b*20) * (1+(math.random()*2))

balls[#balls+1] = ball

world:insert(ball.sprite)

– *******************************************
– taking this line out reduces fps to 7fps :S
– *******************************************
ball.sprite.isVisible=false
– *******************************************

ball.sprite.x=ball.xpos
ball.sprite.y=ball.ypos

end

end
function update(event)

local ball, ypos, bsprite

world.y = world.y - moveSpeed

world.ypos = world.y

for b=1, 10000, 1 do

ball=balls[b]

ballsprite = ball.sprite

– ******************************************
– reading a sprite.y value is a SLOW operation
– read it’s object value instead
– same for world.y / world.ypos
– ******************************************
– ypos = ballsprite.y + world.y
ypos = ball.ypos + world.ypos
– ******************************************

ytop = ypos - h
ybottom = ypos + h

if(ybottom > 0 and ytop < 480) then

ballsprite.isVisible=true

else

– **********************************
– adding this line slows things down
– from 30fps to 15fps!
– **********************************
– ballsprite.isVisible=false
– **********************************

end

end

end

local function onTouch(event)

local touchY = event.y

moveSpeed = 0-(240 - touchY)/4

end

init()

Runtime:addEventListener(“enterFrame”, update)
Runtime:addEventListener(“touch”, onTouch)

local fps = require(“fps”)
local performance = fps.PerformanceOutput.new();
performance.group.x, performance.group.y = display.contentWidth/2, 0;
performance.alpha = 0.6; [/lua] [import]uid: 6645 topic_id: 3618 reply_id: 303618[/import]

I am going to go out on a limb here and throw some ideas around.

First, 10000 objects on the device is likely to get <1fps on an iphone 3g… Not sure about others.

.x and .y coordinates probably have to go through an extra calculation based on whatever the :setReferencePoint() of the object. However, I have no idea if there is a way for that to happen when trying to read a value of an object. Is there a way to setup some sort of trigger function that fires when reading a value? I dont know.

.isVisible = false must cause many other functions to be called after Corona notices its no longer supposed to be visible, causing slowdown from code that you have no control over.

However, I just noticed that you are naming a local variable ‘bsprite’ in that update function, but are not using that local variable. Instead, ‘ballsprite’ is being used, and that variable may end up being scoped as a fully global variable, which is likely to slow down reading from that variable compared to a local one.
[import]uid: 8541 topic_id: 3618 reply_id: 11587[/import]

yeah that bsprite was an error in post, but the forum edit doesnt work on initial posts. in my code it’s actually right.

my point here wasnt to get 10,000 sprites actually running on a phone. it was to indicate that there are performance issues with certain commands. but yes, i hadn’t thought about the reference point.

thanks for the input

j. [import]uid: 6645 topic_id: 3618 reply_id: 11626[/import]

Maybe try using a function call to toggle that setting so that it operates outside of the runtime event. [import]uid: 11024 topic_id: 3618 reply_id: 12508[/import]

when would I do it then?.. the check needs to happen constantly… although the loop could be optimized because some objects in the array are not going to be anywhere near the visible screen anyway [import]uid: 6645 topic_id: 3618 reply_id: 12510[/import]

seems the solution is

[lua]if(leftcheck and rightcheck) then
tile.isVisible=true
elseif(tile.isVisible) then
tile.isVisible=false
end[/lua]

as opposed to

[lua]if(leftcheck and rightcheck) then
tile.isVisible=true
else
tile.isVisible=false
end[/lua]

will do further tests [import]uid: 6645 topic_id: 3618 reply_id: 12522[/import]

any new update on the performance test? [import]uid: 11334 topic_id: 3618 reply_id: 13053[/import]

This is an awesome tip. Once you get to a conclusion it would be cool to post it on here.

http://developer.anscamobile.com/forum/2010/10/16/game-optimizing-techniques-how-get-60-fps-consistently [import]uid: 8192 topic_id: 3618 reply_id: 13070[/import]

@jmp909 any news on your tests? [import]uid: 8192 topic_id: 3618 reply_id: 13456[/import]

no sorry … the next step would be to use some sort of spatial indexing so instead of looping over all 10000 objects i’m only testing the ones near the current viewport, as testing items that are a long way away is obviously wasteful as they’ll never be seen yet anyway.

[import]uid: 6645 topic_id: 3618 reply_id: 13462[/import]

i tried this here
http://developer.anscamobile.com/forum/2010/12/11/another-scrolling-performance-test

results dont seem to be ideal, but i dont have a device at the moment, and it’s only been tested on a 3G [import]uid: 6645 topic_id: 3618 reply_id: 14060[/import]