Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

[Tips] Optimization 101
Started by Danny Dec 02 2011 06:45 PM

* * * * * 8 votes
87 replies to this topic
[TOPIC CONTROLS]
Page 3 of 4 1 2 3 4
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#51

reyanthonyrenacia

[GLOBAL: userInfoPane.html]
reyanthonyrenacia
  • Contributor

  • 121 posts
  • Corona SDK

yow DANNY!! thnx so much for this speed gems!! my eyes were glowing as i was reading the tips! ^_______^  i laughed at my "bad way" programming.daym! am such a transgressor!  looking toward for MOOORE!! hope you keep us posted :)



[TOPIC: post.html]
#52

reyanthonyrenacia

[GLOBAL: userInfoPane.html]
reyanthonyrenacia
  • Contributor

  • 121 posts
  • Corona SDK

Added two more sections to the first post

7) Updating Objects : Only do it when you have to.

8) Creating objects : Things to always remember.

uid: 84637 topic_id: 18550 reply_id: 105892

where is the updated post



[TOPIC: post.html]
#53

bryan.m.mitchell

[GLOBAL: userInfoPane.html]
bryan.m.mitchell
  • Observer

  • 25 posts
  • Corona SDK

Using an enum to compare strings is only for when you have a specific set of strings you are working with, correct?



[TOPIC: post.html]
#54

Jam Paraiso

[GLOBAL: userInfoPane.html]
Jam Paraiso
  • Enthusiast

  • 98 posts
  • Corona SDK

Great Tips :) Helps me alot!! Thank yuo very much



[TOPIC: post.html]
#55

Czepta

[GLOBAL: userInfoPane.html]
Czepta
  • Observer

  • 22 posts
  • Corona SDK

Great list learned a lot. Particularly the 'params' tip and creating functions within the spawn function.



[TOPIC: post.html]
#56

wojtekjakubo

[GLOBAL: userInfoPane.html]
wojtekjakubo
  • Observer

  • 5 posts
  • Corona SDK

about #6:

 

There is an issue with that example (at least for me). It doesnt work - particulary the 'for' loop at the end which limit is #myButtons.

 

I found that as I got to the point in my project when i have a table of tables:

 

local TierData = {
  ['tier1'] = {
    oneBlahData = 1,
    otherBlahData = 'someBlahString',
    },  
  ['tier2'] = {
    oneBlahData = 2,
    otherBlahData = 'someBlahOtherString',
    },
}
 

 

 

 

and i've tried to access it by going TierData[i], etc. But first i'd like to do an error check:

 

local function calculateSegmentProbability(tier)
  local t = --do some stuff to convert 'tier1' to 1
  if (t>#TierData) then
    print("Warning in 'calculateSegmentProbability' - dont have next tier data, using last data found instead...")
    t = #TierData
  end
  --do stuff
end

and it's failing, because #TierData is returning '0' - zero.

 

One way of solving it is to loose the ['tierX'] handlers, but they're really informative. From http://lua-users.org/wiki/TablesTutorial at the bottom i get that this form of table is called "unordered set", but there isn't any information about how to get the length of that besides looping through all elements - which i assume using is done by using 'pairs'.

 

Any one have any ideas of how to solve it?



[TOPIC: post.html]
#57

jennymarlon

[GLOBAL: userInfoPane.html]
jennymarlon
  • Observer

  • 1 posts
  • Corona SDK

Thanks for sharing such a great optimization technique. It helped me a lot because I had soem problems in optimization.



[TOPIC: post.html]
#58

PickionGames

[GLOBAL: userInfoPane.html]
PickionGames
  • Enthusiast

  • 67 posts
  • Corona SDK

I am loving #6 it is really shortening the amount of repeating myself I am doing with button functions.



[TOPIC: post.html]
#59

xpol-vanci

[GLOBAL: userInfoPane.html]
xpol-vanci
  • Observer

  • 9 posts
  • Corona SDK

#1, Is not necessary when using LuaJIT.

 

Does corona use LuaJIT?



[TOPIC: post.html]
#60

espace3d

[GLOBAL: userInfoPane.html]
espace3d
  • Contributor

  • 377 posts
  • Corona SDK

hi, i try the tip with the buttons but with the lib widget.newbutton

the first example without improvements

--REQUIRED-------------------------------------------------------------------------------------------------------------------------------------
local widget = require( "widget" )

--TEXT INFORMATION-------------------------------------------------------------------------------------------------------------------------------------
local textInfo1 = display.newText("", 240,105,native.systemFont,100)
textInfo1:setFillColor(1,0,0)
isButtonClick = 0

local function buttonTouchLeft( event )
    if ( event.phase == "began" and isButtonClick == 0 ) then
    textInfo1.text = "(".."touchleft"..")"
    end
end
 
local function buttonTouchRight( event )
    if ( event.phase == "began" and isButtonClick == 0 ) then
    textInfo1.text = "(".."touchright"..")"
   end
return textInfo1
end

local button1 = widget.newButton
{
    width = 240,
    height = 120,
    defaultFile = "buttoninactif.png",
    overFile = "buttonpressed.png",
    label = "button",
    onEvent = buttonTouchLeft
}
button1.x = 53
button1.y = 225
button1.xScale = 0.5
button1:setLabel(  )

local button2 = widget.newButton
{
    width = 240,
    height = 120,
    defaultFile = "buttoninactif.png",
    overFile = "buttonpressed.png",
    label = "button",
    onEvent = buttonTouchRight
}
button2.x = 428.5
button2.y = 225
button2.xScale = 0.5
button2:setLabel(  )

and the optimization but i have an error "attempt to index field"

this method is incompatible with the widget? or I have do something wrong ?

local widget = require( "widget" )

--TEXT INFORMATION-------------------------------------------------------------------------------------------------------------------------------------
local textInfo1 = display.newText("", 240,105,native.systemFont,100)
textInfo1:setFillColor(1,0,0)
isButtonClick = 0

--BOUTTON-----------------------------------------------------------------------------------------------------------------------------------------
--Table to store the buttons
local myButtons = {}

myButtons[1] = widget.newButton
myButtons[1].myId = "LeftButton"  --Set the buttons id
myButtons[1].width = 240
myButtons[1].height = 120
myButtons[1].defaultFile = "buttoninactif.png"
myButtons[1].overFile = "buttonpressed.png"
myButtons[1].label = "buttonL"
myButtons[1].x = 53
myButtons[1].y = 225
myButtons[1].xScale = 0.5
myButtons[1].setLabel = "Gauche"

myButtons[2] = widget.newButton
myButtons[2].myId = "RightButton"  --Set the buttons id
myButtons[2].width = 240
myButtons[2].height = 120
myButtons[2].defaultFile = "buttoninactif.png"
myButtons[2].overFile = "buttonpressed.png"
myButtons[2].label = "buttonR"
myButtons[2].x = 428
myButtons[2].y = 225
myButtons[2].xScale = 0.5
myButtons[2].setLabel = "Droit"


--Function to handle our buttons
local function handleButtons(event)
     local target = event.target

     --Handle action for each different button
     if target.myId == "LeftButton" then
            textInfo1.text = "(".."touchleft"..")"
     elseif target.myId == "RightButton" then
            textInfo1.text = "(".."touchright"..")"
     end
      
     return true
end

--Add event listeners for all the buttons
for i = 1, #myButtons do
    myButtons[i]:addEventListener("tap", handleButtons)
end


[TOPIC: post.html]
#61

Burhan J

[GLOBAL: userInfoPane.html]
Burhan J
  • Contributor

  • 131 posts
  • Corona SDK

Hi @espace3d

 

Your error is because your syntax is wrong. It should be like your first example.

 

Anyway, based on your first code you can do this way.

You can use id in widget.newButton to name your button
REQUIRED-------------------------------------------------------------------------------------------------------------------------------------
local widget = require( "widget" )

--TEXT INFORMATION-------------------------------------------------------------------------------------------------------------------------------------
local textInfo1 = display.newText("", 240,105,native.systemFont,100)
textInfo1:setFillColor(1,0,0)
isButtonClick = 0
local button = {}

local function buttonTouch( event )
    local target = event.target
    if ( event.phase == "began" and isButtonClick == 0 ) then
    	if  target.id == "LeftButton" then
    		textInfo1.text = "("..target.id..")"
    	elseif  target.id == "RightButton" then	
    		textInfo1.text = "("..target.id..")"
    	end
   end
return textInfo1
end

button[1] = widget.newButton
{
    width = 240,
    height = 120,
    defaultFile = "buttoninactif.png.png",
    overFile = "buttonpressed.png",
    label = "button",
    id = "LeftButton",
    onEvent = buttonTouch
}
button[1].x = 53
button[1].y = 225
button[1].xScale = 0.5
button[1]:setLabel(  )

button[2] = widget.newButton
{
    width = 240,
    height = 120,
    defaultFile = "buttoninactif.png.png",
    overFile = "buttonpressed.png",
    label = "button",
    id = "RightButton",
    onEvent = buttonTouch
}
button[2].x = 428.5
button[2].y = 225
button[2].xScale = 0.5
button[2]:setLabel(  )
 

Good Luck!

 

burhan



[TOPIC: post.html]
#62

espace3d

[GLOBAL: userInfoPane.html]
espace3d
  • Contributor

  • 377 posts
  • Corona SDK

Hi@Burhan

 

Thanks it's work now.

 

Maybe you can answer me.
 
What is the fps not to exceed in order not to compromise the cpu used

I am currently using 60fps for a better display but I would increase ... what is the limit not to be exceeded
?


[TOPIC: post.html]
#63

Burhan J

[GLOBAL: userInfoPane.html]
Burhan J
  • Contributor

  • 131 posts
  • Corona SDK

CoronaSDK will ignore any values other then 30 or 60 fps. Read here,

 

http://docs.coronalabs.com/guide/basics/configSettings/index.html#fps

 

 

burhan



[TOPIC: post.html]
#64

bexphones

[GLOBAL: userInfoPane.html]
bexphones
  • Enthusiast

  • 37 posts
  • Corona SDK

hi, this tip doesn't work with me...

 

Is there an error in the snippet or something changed ?

--Table to store the buttons
local myButtons = {}

myButtons["Pause"] = display.newImage("pause.png")
myButtons["Pause"].myId = "Pause"  --Set the buttons id

myButtons["Shoot"] = display.newImage("shoot.png")
myButtons["Shoot"].myId = "Shoot" --Set the buttons id

myButtons["Move"] = display.newImage("move.png",200,200)
myButtons["Move"].myId = "Move" --Set the buttons id

myButtons["Retry"] = display.newImage("retry.png", 10,10)
myButtons["Retry"].myId = "Retry" --Set the buttons id

--Function to handle our buttons
local function handleButtons(event)
     local target = event.target

     --Handle action for each different button
     if target.myId == "Pause" then
         print("pause")
     elseif target.myId == "Shoot" then
         print("shoot")
     elseif target.myId == "Move" then
         print("move")
     elseif target.myId == "Retry" then
         print("retry")
     end
      
     return true
end

--Add event listeners for all the buttons
for i = 1, #myButtons do
    myButtons[i]:addEventListener("tap", handleButtons)
end


[TOPIC: post.html]
#65

forewar

[GLOBAL: userInfoPane.html]
forewar
  • Observer

  • 15 posts
  • Corona SDK

Very useful topic, it helped me a lot! Especially #2

Thanks!



[TOPIC: post.html]
#66

endygwa

[GLOBAL: userInfoPane.html]
endygwa
  • Enthusiast

  • 41 posts
  • Corona SDK

Very useful OP, thanks.

 

Could someone explain why this:

 

local mRand = math.random
local myRand = mRand(1, 10)

 

is faster than this:

 

local myRand = math.random(1, 10)

 

Thanks
endy
 



[TOPIC: post.html]
#67

Hendrix000007

[GLOBAL: userInfoPane.html]
Hendrix000007
  • Contributor

  • 177 posts
  • Corona SDK

When you declare a variable that holds the math.random function like mRand you call it once and save it in the variable ready to use whenever you like but if you do local myRand = math.random(1,10) you call the function over and over again in theory it´s like pre-buffering a video and watch it when loaded, compared to the oposite, to pre-buffer the video and when it´s ready buffered and you´re ready to watch you hit refresh (ctrl+r)

, well, a kind of.....LOL



[TOPIC: post.html]
#68

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,905 posts
  • Enterprise

For a simple example like that, it's not really any more efficient.  The principle behind it is that when functions are part of an object/table like random is part of the math object, when ever you use it, Lua has to traverse the math object to find the random entry.  This takes time.  When the object is global, like math is, that process is even more costly.

 

If you're making hundreds or thousands of calls to math.* inside a loop or event handler that is firing rapidly, it's faster to have made functions like "random" local so it's a simple variable rather than a table that has to searched through.

 

Rob



[TOPIC: post.html]
#69

endygwa

[GLOBAL: userInfoPane.html]
endygwa
  • Enthusiast

  • 41 posts
  • Corona SDK

For a simple example like that, it's not really any more efficient.  The principle behind it is that when functions are part of an object/table like random is part of the math object, when ever you use it, Lua has to traverse the math object to find the random entry.  This takes time.  When the object is global, like math is, that process is even more costly.

 

If you're making hundreds or thousands of calls to math.* inside a loop or event handler that is firing rapidly, it's faster to have made functions like "random" local so it's a simple variable rather than a table that has to searched through.

 

Rob

 

Hi Rob,

 

Thanks for the explanation. At the moment I use math.random quite a lot, but it has to be within a small function and I call it only once within the function.

Since a localized math.random would be lost when exiting the calling function and I use math random only once within the calling function, if my understanding is correct there would be no benefit to localize math.random in this specific case. Right?

 

Thanks

endy



[TOPIC: post.html]
#70

Hendrix000007

[GLOBAL: userInfoPane.html]
Hendrix000007
  • Contributor

  • 177 posts
  • Corona SDK

Multiplication has higher precedence in lua and so it´s faster than division --theoretically guys...theoretically :)

 

When you want to devide the value of something like i.e. the width of some variable:

local _W = display.contentWidth
local _hW = _W / 2 -- half width of the screen

This is slower than:

local _hW = _W * 0.5

In my oppinion it´s better to practice this even though it doesn´t make any difference in most cases



[TOPIC: post.html]
#71

Hendrix000007

[GLOBAL: userInfoPane.html]
Hendrix000007
  • Contributor

  • 177 posts
  • Corona SDK

One thing I have experienced specially when working with Composer and earlier Storyboard is that you work sometimes with different scopes and this can result in faulty code in simulator

Many times this is omited if you do forward declarations in the start of the script like:

local myVar1, myVar2
local myListeners = {}

Now the variables are local but accessable from anywhere in the present script

At least this is my experience and it is one among many ways of getting variables accessable. It takes a littlebit more time and produces some more code but you may experience that this is well spend time when you start the degugging of your code ;D

 

I also like to take this opportunity to say that the real beauty of local variables and scoping and privacy/sandboxing is that if you need a variable just for some seconds like in a function you can make it local inside the function like this:

local var1 -- This variable is accessable from everywhere in the script
 
local function myFunction()
local myPrivateVar = "This variable is only accessable and visible from within this function"
return myPrivateVar
end

Hope this can be of help



[TOPIC: post.html]
#72

Hendrix000007

[GLOBAL: userInfoPane.html]
Hendrix000007
  • Contributor

  • 177 posts
  • Corona SDK

Debugging

I usually do things like this in main file (I did this in an music app when the music made me crazy while debuggin other parts than audio or when I wanted to listen to spotify instead of the gamesound:

local debugging = true

Now in other scripts and classes/modules i can do:

if debugging == true then audio.volume = 0 end

You can also have different levels of the variable "debugging" ...we go back to main.lua file and write:

local myText = "Hey, I´m debugging text over here!"
local debugChoice = {"audioDebug", "textDebug", "allDebug"}
local debug = debugChoice[1] -- If i like to debug the musicpart of my app
 
if debugging == debugChoice[1] then audio.volume = 0 end
if debugging == debugChoice[2] then print(myText.text) end

Hope this can be helpfull, it really is for me


  • sirmania likes this

[TOPIC: post.html]
#73

endygwa

[GLOBAL: userInfoPane.html]
endygwa
  • Enthusiast

  • 41 posts
  • Corona SDK

If we are going to use display.contentWidth or other constants of display.*, isn't it better to put the values in global variables instead of having to call display.* everytime? Of course global variables take some memory, but in terms of speed it should be better right?



[TOPIC: post.html]
#74

StarCrunch

[GLOBAL: userInfoPane.html]
StarCrunch
  • Contributor

  • 814 posts
  • Corona SDK

@Hendrix000007

 

Regarding local variables, you can also create temporary scopes in code via do / end, like so:

do
  local my_var1, my_var2 = "Private", "Variable"

  -- Do stuff with these...
end


[TOPIC: post.html]
#75

Hendrix000007

[GLOBAL: userInfoPane.html]
Hendrix000007
  • Contributor

  • 177 posts
  • Corona SDK

Hi endygwa

The display.contentWidth was just ment as an example for the use of * 0.5 rather than doing /2.

To your question regarding global variable vs. local on the variable _W that is just a shortcut to the display.contentWidth variable, I guess it´s a matter of taste really when it comes to G´s and locals in this example. Its pros and cons to the use of globals.

I always have good cleanup routines when dealing with globals (It can be tricky if you dont do this and you i.e. want to reset your game and it wont flush the globals...then you´ll need cleanup routines for that!, the locals is dealth with by the garbage collector and you can force it to collect if you like too )

 

If you ask me, I agree to the aproach of doing some global declaration in the main.lua file, then you know where the variable is and how long it lives. Like if you put your score on the runtime global table: _G  like _G.score = {} you can check it by doing: 

_G.score = 500
 
for k,v in pairs (_G) do
print( k )
end
--[[
this prints out the global variable table-names and now you will find your score in here if it exists
What I often do while debugging is that I put a print command inside an if clause like this:
--]]
if nil ~= _G.score then
print( _G.score )
end

 

Simulator =>>  500

Hope this helps :)




[topic_controls]
Page 3 of 4 1 2 3 4
 
[/topic_controls]