[Tips] Optimization 101

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

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 ?

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

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

burhan

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

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

Thanks!

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
 

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

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

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

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

[lua]

local _W = display.contentWidth

local _hW = _W / 2 – half width of the screen

[/lua]

This is slower than:

[lua]

local _hW = _W * 0.5

[/lua]

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

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:

[lua]

local myVar1, myVar2

local myListeners = {}

[/lua]

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:

[lua]

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

[/lua]

Hope this can be of help

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:

[lua]

local debugging = true

[/lua]

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

[lua]

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

[/lua]

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

[lua]

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

[/lua]

Hope this can be helpfull, it really is for me

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?

@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

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: 

[lua]

_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

[/lua]

Simulator =>>  500

Hope this helps :slight_smile:

@Rob Miracle

You are like a lexicon man :slight_smile:

thanx

(Disclaimer: Verify this on your target platform before believing this.)

Current testing Results

  • Simulator on Windows 7 PC - num ^ 0.5 = 40%+ faster
  • iPad Air Gen 1 (iOS 8.02) - math.sqrt() = %21 faster

The Real Take Away

Test any optimization on your target machine before assuming it will work. 

The Short Description Of This Tip (for the attention-challenged  ;) )

local sqrt( num ) return num ^ 0.5 end

may be  faster than:

local mSqrt = math.sqrt local sqrt( num ) return mSqrt( num ) end

The Long Description Of This Tip

I recently answered a math question which led me to calculate the Nth root of a number.  The equation for this is:

local function( num, root )    return num ^ 1/root end

While there is nothing exciting about this, it suddenly occurred to me that this might be faster than the math.sqrt function for root == 2.  

It is!  … or is it?

On my windows test machine, num^0.5 is almost 40% faster than a localized math.sqrt() call.  However, on my iPad Air math.sqrt is 21% faster

Here is my test code:

local function round(val, n) if (n) then return math.floor( (val \* 10^n) + 0.5) / (10^n) else return math.floor(val+0.5) end end local function test1( num ) local mSqrt = math.sqrt local startTime = system.getTimer() local v for i = 1, num do v = mSqrt(i) end local endTime = system.getTimer() local dt = (endTime-startTime) print("math.sqrt x " .. num .. " == " .. dt .. " ms" ) return dt end local function test2( num ) local mSqrt = math.sqrt local startTime = system.getTimer() local v for i = 1, num do v = i^0.5 end local endTime = system.getTimer() local dt = (endTime-startTime) print("M^0.5 x " .. num .. " == " .. dt .. " ms" ) return dt end local t1 = 0 local t2 = 0 t1 = t1 + test1(1000000) t1 = t1 + test1(1000000) t1 = t1 + test1(1000000) t2 = t2 + test2(1000000) t2 = t2 + test2(1000000) t2 = t2 + test2(1000000) if( t1 \> t2 ) then print(" M^0.5 is faster by " .. round( 1 - t2/t1,2 ) \* 100 .. "%" ) else print(" math.sqrt is faster by " .. round( 1 - t1/t2,2 ) \* 100 .. "%" ) end

@roaminggamer

On that same note, I’ve found multiplying by powers of 2, e.g. x * 2^power, quite a lot faster than bit.lshift() or math.ldexp() (with the localizations, of course) in the Windows simulator. On device, I don’t know if I’ve done any tests. Likewise x^2 versus x * x (lookup local, invoke operator with constant, vs. lookup local, lookup “another” local, invoke operator).

On the subject of bitwise ops, where possible, I tend to favor the + and - operators over of bit.bor() and bit.band() / bit.bnot(). The % operator, on the other hand, still seemed pretty expensive vs. bit.band().

Any non-Windows numbers, or contrary results on Windows itself, would be much appreciated!

For optimization geeks, I created an additional way to test the above (requires above code):

local function visualizeResults2( test1, test2, size, num, doPower ) local t1 = 0 local t2 = 0 size = size or 2 num = num or 100 local t1 = 0 local t2 = 0 local count = 1 local width = round(display.contentWidth/size) local height = round(display.contentHeight/size) local yield = coroutine.yield print("Running ", width \* height \* num \* 2, " calculations." ) local lastTime = getTimer() local timerID local wrapped = coroutine.wrap( function( event ) for i = 1, height do for j = 1, width do if( doPower ) then t1 = test1( num, 10^(count-1) ) t2 = test2( num, 10^(count-1) ) else t1 = test1( num, count ) t2 = test2( num, count ) end local tmp = display.newRect( (j-1) \* size, (i-1) \* size, size, size ) tmp.anchorX = 0 tmp.anchorY = 0 if( t1 \> t2 ) then --if( count%7 == 0 ) then tmp:setFillColor(0,1,0) else tmp:setFillColor(1,0,0) end count = count + 1 --if( count%100 == 0 ) then yield() end if( getTimer() - lastTime \> 25 ) then lastTime = getTimer() yield() end end end print("DONE") timerID = event.source timer.cancel(timerID) end ) timer.performWithDelay( 1, wrapped, 0 ) end visualizeResults2( test1, test2, 8, 10000, true )

This produces a full page visualization of what numbers are faster one way or the other.  Interestingly for certain powers of 10, one method is faster than the other.

Note: I think  I have an error in the above code as it crashes at the end. oops!

@StarCrunch

Yes, it is actually a real handy little thing the do command

If there is a certain order you like to fire functions and blocks of code, you can put them in do blocks

and the way you show it here is really nice because the variables lives just as long as the do block is active

when it´s done executing, the scope is gone and all the local variables in the scope is released too

I use it quite often