Member functions - do they affect performance or cause memory-leaks?

Hi,

I just read a tutorial about scopes for functions:

http://blog.anscamobile.com/2011/09/tutorial-scopes-for-functions/
(originally posted by Jayant Varma of OZ Apps on http://howto.oz-apps.com/2011/09/scopes-for-functions.html)

In one of the examples in the ‘Member functions’ section we can find a non-localised function

[lua]resultingObject.changeColor(theColor)[/lua]

so we can use that function later in the code when we are out of scope of spawnObject function

Example:
[lua]local function spawnObject()
local resultingObject = display.newRect(10,10,100,100)

function resultingObject.changeColor(theColor)
resultingObject:setFillColor(theColor[1],theColor[2],theColor[3])
end

local function onTouch(event)
if “ended” == event.phase then
print(“touched rectangle”)
end
end

resultingObject:addEventListener(“touch”,onTouch)

return resultingObject
end

local xTemp = spawnObject()
xTemp.changeColor({255,0,255})[/lua]
On the other hand we should always try to use locals. Moreover, functions are variables too in Lua, as we can read at Lua: Best Practices section on http://developer.anscamobile.com/content/performance-and-optimization

Use locals (i.e. avoid global variables)
Avoid global variables. Period. In Lua, you will sacrifice performance if you use global variables. When in doubt, precede your variable declarations with local .
This applies even to functions. In Lua functions are variables too. In long loops, it’s better to assign a function to a local variable

As I understand, that member function (changeColor) is not local and ‘lives’ after the spawnObject() function finishes execution (and destroy all ‘nested’ locals)
Could anyone explain me

  1. Can using non-localised member function in that scenario affect performance?
  2. Can we consider that changeColor function is a global variable? If so, what about garbage collection and memory-leaks?

Cheers,
Patryk [import]uid: 51816 topic_id: 24950 reply_id: 324950[/import]

It’s not the case that the changeColor function in your example is a global variable. If you break down the objects, consider what exactly they are:

[lua]xTemp[/lua] is a local variable whose contents are returned by the spawnObject function. Within it:

[lua]resultingObject[/lua] is a local variable whose contents are a Corona display object, which is just a Lua table with some fancy stuff in it, but if you ignore that, think about this code instead:

[lua]local resultingObject = {}

resultingObject.value = “stuff”[/lua]

Would you say resultingObject.value is a global variable? Of course not. But this is no different than that function declaration because these two things are exactly equivalent:

[lua]local resultingObject = {}
function resultingObject.function(stuff) return stuff end[/lua]

and

[lua]local resultingObject = {}
resultingObject.function = function(stuff) return stuff end[/lua]

Or even

[lua]local resultingObject = { function=function(stuff) return stuff end }[/lua]

There are several things in your posted example code that aren’t ideal, but there aren’t any globals in it. [import]uid: 44647 topic_id: 24950 reply_id: 101320[/import]

Hi @Patryk

Globals are not as evil as people make them out to be. Yes they should be avoided and yes they can create performance problems.

Consider these two blocks of code:

  
counter = 1  
  
for i = 1, 1000000 do  
 counter = counter + 1  
end  

vs.

local counter = 1

for i = 1, 1000000 do
counter = counter + 1
end
[/code]

Since there is more “expense” in fetching a global variable, accessing it a couple of million times ads up in CPU time. In this example, the 2nd option using a local counter variable will perform much better. Now consider this:

global_counter = 1
local counter = global_counter

for i = 1, 1000000 do
counter = counter + 1
end
[/code]

In this case I’m using a global variable, but I’m not looping over it a million times. There is a very negligible performance hit by using a global and localizing it

Now think about this is a more practical sense: the game’s current score and using something like storyboard or Director to manage scenes and you need the score on the gameover scene as well as in the gamelevel scene. There is no harm in using a global variable for that. Lua has a special global table _G for that use.

In your gamelevel.lua file you might update the score every few seconds. Given our processor speed, every few seconds is negligible. Then your score variable is available when you change scenes.

The other issue with globals is you have no guarantee that someone else isn’t using that variable. So if you have a variable named “score”, what’s to prevent some library you got out of the community code from having a global variable named “score”. Now you’re stomping on each other and it creates hard-to-track-down bugs.

So you want to localize where you can, when you can and when its practical. But as long as your use of globals is a) planned, b) thought out, c) not accessed frequently and d) namespaced to avoid collisions with other names, then they are a valid tool in the toolbox.

But most new and even skilled programmers will not do the due diligence necessary to make sure their use of globals is proper.

With regard to leaks, globals leak no more than any other variable. [import]uid: 19626 topic_id: 24950 reply_id: 101329[/import]

@robmiracle

In your example

[lua]global_counter = 1
local counter = global_counter

for i = 1, 1000000 do
counter = counter + 1
end[/lua]

You forgot to mention that when that loop is finished, the result is not what one might expect it to be:

[lua]print( global_counter, counter )
–> 1 1000001[/lua]

Localizing global variables for performance is good practice, but it doesn’t apply to bare values; you wouldn’t do this except for a constant value.

I find great utility in global variables for constants that I will use throughout my app, especially things I need to derive at runtime but don’t want to derive more than once. With constants, I don’t have to worry about garbage collection, and if I need to I can localize them in a tight loop without worrying about modifications.

Also, because globals are never out of scope, they’re never considered garbage, even if *you* know that you’re done with them. That’s what we mean when we claim globals leak more memory than locals. [import]uid: 44647 topic_id: 24950 reply_id: 101358[/import]

toby2, robmiracle - thanks for the reply

@toby2

Thanks for the explanation. That is what I thought at the beginning - that the functions are ‘copied’ to the object during the creation. (just like any other parameter like object.value, object.name etc)

So when the object is deleted - the ‘copied function’ in it is deleted as well.
Quite clear :slight_smile:

There are several things in your posted example code that aren’t ideal,

It would be great if you could tell me what things did you mean?
The example was not mine - it was copied from the “scopes-for-functions” tutorial (link in my first post)
I wanted to use member function to create nice and tidy code for ‘enemy’ - so whenever a new enemy is created and added for example to array [lua]allEnemies = {}[/lua]- it comes with all necessary functions (like touch listeners or destroy functions).

I guess I have to rethink the concept as I am not sure whether it is good to pass everything (functions, listeners) to every new object - I mean that it will create a lot of redundant code in every instance of enemy.

Additionally it may cause big performance issues
If I think right looking at your example
[lua]local resultingObject = { function=function(stuff) return stuff end }[/lua]
and we pass that resultingObject as a param for other functions - it will also pass the included function (which is inside resultingObject) as a param for the other function. Have a look at that link:
http://trac.caspring.org/wiki/LuaPerformance
go to: TEST 8: functions as param for other functions

Don’t you think that it is it might me catastrophic for the performance? (10 times slower as in example in TEST 8)

Anyway - it would be great if you could tell me what was wrong with that example.

@robmiracle
Thank you for the explanation.
I was aware that accessing a global variable takes longer than accessing a local one.
I was just not sure if that function should be considered as global or local?
And if it was global - what should I do with it? How should I remove it?
I think that toby2 explained that to me correctly.

Regarding ‘score’ - I am actually using storyboard and I guess the best way to transfer a variable betwwen the scenes is to use something like:
[lua]local storyboard = require “storyboard”
local score – use to update score during a gameplay
storyboard.score= score --use to updated score when changing the scenes[/lua]
That method was recommended in
http://blog.anscamobile.com/2011/11/common-storyboard-api-questions/#how-do-you-transfer-data-variables-between-scenes

Thanks for encouraging me to using global variables :wink: It is recommended NOT to use them in so many posts and tutorials that it was like mantra for me :wink:
[import]uid: 51816 topic_id: 24950 reply_id: 101371[/import]

“Never use globals” is one of those rules that you’re allowed to break as long as you understand the rule you’re breaking and why you’re breaking it.:slight_smile:

What I mean by that example code not being ideal is that it’s got a kind of dashed-out-in-a-hurry feel to it. The author is using object-oriented lingo to talk about it (“member functions”, e.g.) but not actually doing any object-orientated code example, then later in the post talks about putting functions in a table as though it’s something he hasn’t already done in his example. Really, you’re not going to want to use that code block as a blueprint for an object factory is all I meant.

About that ‘functions-as-parameters’ thing, if you were to pass ‘resultingObject’ as a parameter into some function, all you’re passing is a reference to a table to give it scope. Performance should be on par with the ‘good’ outcome of that performance test #8. In that ‘bad’ code example, the performance hit is in declaring and allocating a closure (anonymous function) 1 million times in a tight loop. [import]uid: 44647 topic_id: 24950 reply_id: 101392[/import]

Is there a rule for when to define functions as locals?

I’ve been declaring functions like this for a while:

local function myFunction ()  
...  
end  

but I regularly see people omitting “local” and just defining functions in main.lua as

function myFunction ()  
...  
end  

Any advice? [import]uid: 1560 topic_id: 24950 reply_id: 101415[/import]

Functions, like variables should be declared local when possible. If the person specifically does not need that function to be scoped globally, its a sign they have programed themselves into a box and its a hack to get around forward declaration problems.

Example.

  
local function functionA()  
 functionB()  
end  
  
local function functionB()  
 -- do stuff..  
end  
  
functionA()  
  

This will cause an error in Corona SDK because functionB has not been declared when functionA calls it.

So someone who doesn’t understand forward declarations will remove the local from functionB and it will work.

[import]uid: 19626 topic_id: 24950 reply_id: 101421[/import]

Globals and “Super Globals” have their place, but it’s a good idea to avoid using them with display objects and other memory intensive stuff.

Typically I use them to carry “flags” that change my apps behavior. For instance, if Android do X, if iOS do Y. [import]uid: 36054 topic_id: 24950 reply_id: 101423[/import]