Performance Tips for iterating through large tables?

Hi all,

I am having some performance issues iterating through a large array (around 400 records but could be larger). Seems to be taking around 13.5 seconds on iOS devices but upwards to 30 seconds on Android for it to finish.

If it helps to understand the scenario- I am developing a multi-player game and I have a screen to play with your facebook friends, similar to any other multi-player game like words with friends or draw something. I am iterating through all the user’s facebook friends so the array could be quite large for some users. 

Through each iteration I am populating 2 images, (same 2 images iterated over and over), as well as displaying 2 text objects on the screen.

I can provide the code if that helps…just looking for any tips anyone has so I can hopefully speed up performance…most users will not want to wait 30 seconds and think the game is frozen.

Thanks in advance!

-Clark

Hi Clark,

Most likely this is because of the text display. Rendering fonts to bitmaps (internally) is inherently not the fastest thing. Several text objects won’t cause any noticeable hit, but 400 or more will.

Is there any way you can show just some on the screen, but not all at once? Can you post your current code how it’s being done now?

Thanks,

Brent

Yea I thought about just iterating through part of the array and then trying to detect when someone scrolls down a certain bit and then run through a little bit more of the array…but then I was thinking this might not produce the smoothest scrolling results as I was thinking it would pause briefly while the array iterated again.

Here is the code I currently run through the array:

for i=1,#data do                 matchCounterI = matchCounterI + 1                 local id = data[i].id                 local name = data[i].name                 local playStatusText = "INVITE"                                  if (data[i].installed) then                     playStatusText = "PLAY"                 end                                                  local backgroundMiddleC = display.newImageRect( "scrollimageMiddle.png", 300, 40 )                 backgroundMiddleC.x = 160                 backgroundMiddleC.y = 13 + (40 \* turnsCounter)                 scrollView:insert(backgroundMiddleC )                                  local fbName = display.newText( name, 0, 0, native.systemFontBold, 14 )                 fbName:setTextColor( 0 )                 fbName:setReferencePoint( display.CenterLeftReferencePoint )                 fbName.x, fbName.y = 40, 5 + (40 \* turnsCounter)                 scrollView:insert( fbName )                                  if (data[i].installed) then                     local fbDesc = display.newText( "Start a new game!", 0, 0, native.systemFont, 9 )                     fbDesc:setTextColor( 0 )                     fbDesc:setReferencePoint( display.CenterLeftReferencePoint )                     fbDesc.x, fbDesc.y = 40, 21 + (40 \* turnsCounter)                     scrollView:insert( fbDesc )                 else                     local fbDesc = display.newText( "Invite to Movie Trivia Match Up!", 0, 0, native.systemFont, 9 )                     fbDesc:setTextColor( 0 )                     fbDesc:setReferencePoint( display.CenterLeftReferencePoint )                     fbDesc.x, fbDesc.y = 40, 21 + (40 \* turnsCounter)                     scrollView:insert( fbDesc )                 end                                  playGameLabel[matchCounterI] = display.newImageRect( "blankButton.png", 50, 25 )                 playGameLabel[matchCounterI].x = 270                 playGameLabel[matchCounterI].y = 13 + (40 \* turnsCounter)                 playGameLabel[matchCounterI].id = id                 scrollView:insert( playGameLabel[matchCounterI] )                                  local playGameLabelText = display.newText( playStatusText, 0, 0, native.systemFontBold, 12 )                 playGameLabelText:setTextColor( 0 )                 playGameLabelText:setReferencePoint( display.CenterReferencePoint )                 playGameLabelText.x, playGameLabelText.y = 270, 13 + (40 \* turnsCounter)                 scrollView:insert( playGameLabelText )                                  playGameLabel[matchCounterI]:addEventListener( "touch", playGameLabelTouch )                                      turnsCounter = turnsCounter + 1                                  end  

Thanks 

Hi @bonesmalone133,

Since 3 of the 4 text fields in each iteration are static, could you just use rendered (image) objects for those? And then match, as closely as possible, the output “name” text to those? Just an idea… it might really improve performance.

Brent

Hi Brent,

Thanks I have taken your suggestions and it did help a bit - got it down to about 6 seconds now. I think I will look into trying to only load part of the array on first load and load more of it as you scroll. Curious to see how performance is when I do that.

Thanks again.

-Clark

Hi Clark,

Most likely this is because of the text display. Rendering fonts to bitmaps (internally) is inherently not the fastest thing. Several text objects won’t cause any noticeable hit, but 400 or more will.

Is there any way you can show just some on the screen, but not all at once? Can you post your current code how it’s being done now?

Thanks,

Brent

Yea I thought about just iterating through part of the array and then trying to detect when someone scrolls down a certain bit and then run through a little bit more of the array…but then I was thinking this might not produce the smoothest scrolling results as I was thinking it would pause briefly while the array iterated again.

Here is the code I currently run through the array:

for i=1,#data do                 matchCounterI = matchCounterI + 1                 local id = data[i].id                 local name = data[i].name                 local playStatusText = "INVITE"                                  if (data[i].installed) then                     playStatusText = "PLAY"                 end                                                  local backgroundMiddleC = display.newImageRect( "scrollimageMiddle.png", 300, 40 )                 backgroundMiddleC.x = 160                 backgroundMiddleC.y = 13 + (40 \* turnsCounter)                 scrollView:insert(backgroundMiddleC )                                  local fbName = display.newText( name, 0, 0, native.systemFontBold, 14 )                 fbName:setTextColor( 0 )                 fbName:setReferencePoint( display.CenterLeftReferencePoint )                 fbName.x, fbName.y = 40, 5 + (40 \* turnsCounter)                 scrollView:insert( fbName )                                  if (data[i].installed) then                     local fbDesc = display.newText( "Start a new game!", 0, 0, native.systemFont, 9 )                     fbDesc:setTextColor( 0 )                     fbDesc:setReferencePoint( display.CenterLeftReferencePoint )                     fbDesc.x, fbDesc.y = 40, 21 + (40 \* turnsCounter)                     scrollView:insert( fbDesc )                 else                     local fbDesc = display.newText( "Invite to Movie Trivia Match Up!", 0, 0, native.systemFont, 9 )                     fbDesc:setTextColor( 0 )                     fbDesc:setReferencePoint( display.CenterLeftReferencePoint )                     fbDesc.x, fbDesc.y = 40, 21 + (40 \* turnsCounter)                     scrollView:insert( fbDesc )                 end                                  playGameLabel[matchCounterI] = display.newImageRect( "blankButton.png", 50, 25 )                 playGameLabel[matchCounterI].x = 270                 playGameLabel[matchCounterI].y = 13 + (40 \* turnsCounter)                 playGameLabel[matchCounterI].id = id                 scrollView:insert( playGameLabel[matchCounterI] )                                  local playGameLabelText = display.newText( playStatusText, 0, 0, native.systemFontBold, 12 )                 playGameLabelText:setTextColor( 0 )                 playGameLabelText:setReferencePoint( display.CenterReferencePoint )                 playGameLabelText.x, playGameLabelText.y = 270, 13 + (40 \* turnsCounter)                 scrollView:insert( playGameLabelText )                                  playGameLabel[matchCounterI]:addEventListener( "touch", playGameLabelTouch )                                      turnsCounter = turnsCounter + 1                                  end  

Thanks 

Hi @bonesmalone133,

Since 3 of the 4 text fields in each iteration are static, could you just use rendered (image) objects for those? And then match, as closely as possible, the output “name” text to those? Just an idea… it might really improve performance.

Brent

Hi Brent,

Thanks I have taken your suggestions and it did help a bit - got it down to about 6 seconds now. I think I will look into trying to only load part of the array on first load and load more of it as you scroll. Curious to see how performance is when I do that.

Thanks again.

-Clark