Question about performance using external modules or not

In my app I have a square which I use object.fill. I have approximately 36 paints to use in that square. My question is whether it is better to use an external module to locate the paint tables or is there no problem to call it at the top of the current scene which use the 36 paints?

Thanks

DoDi

Well, logically, speaking it is better to require those in a module so you call them from wherever instead of having to redefine them for each file. However, if it is only one file, I would assume that the difference in performance is very minuscule.

@sdktester15

Thanks for your response.  Do you think I need to code this:

package.loaded["myModule"] = nil

in my scenes “hide” or “destroy” to un-require myModule or when I call it at the top

local myModule = require( "myModule" )

and composer destroy is called “myModule” gets automatically un-require cause I set the module call to local?

Why do you need to un-require the module?

Rob

@rob

I think if I un-require the external module, which have 36 paints of 512x512 px is best for app performance.

I feel my device hot while running the App. I managed to drastically lower the texture memory using image sheets even for the background images. Now I’m looking for code optimization to see if I get more performance and my device runs good without heating.

52% of my images are big (512x512, 320x160, etc, and also use @2x images)

Maybe if I require the external module in main.lua and in the scene I will goin to use it is better? Then my app know there is an external module that I’m going to use in some scene. I’m just try to figure out how all interacts to deduce what is the best for my app.

I would like to use this topic to ask a related question. which of these three forms would be the best given the case.

36 paints to load to use in 36 different buttons touch events.

method 1

local paint1 = { type = "image", filename = "images/paint1.png" } local paint2 = { type = "image", filename = "images/paint2.png" } local paint3 = … to paint 36 local function paint1ButtonTouch( event ) if ( event.phase == "ended" ) then square.fill = paint1 end return true end ...36 buttons functions

method 2

local paint1, paint2 … to paint 36 local function paint1ButtonTouch( event ) if ( event.phase == "ended" ) then paint1={type="image",filename="images/paint1.png"} square.fill = paint1 end return true end ...36 buttons functions

method 3

local paint = {} local function paintButtonTouch( event ) if ( event.phase == "ended" ) then paint = nil paint={type="image",filename="images/paint1.png"} square.fill = paint end return true end ...36 buttons functions

thanks in advance
DoDi

Aaah no, it looks like AP Computer Science all over again!

I would assume option three would be better here since it takes out all your requires and makes the code more compact. However, as for performance, I am not too sure. @roaminggamer can take it away from here.

I presume you could use package.loaded[…] = nil on the “did” phase of hide() and the destroy() function.

How about measuring your fps when you use this line on the hide and destroy phases, and then when you don’t? Just to test this out.

FPS stay the same from my perception. Now, if I use the method one, scene load faster than using an external module.

I’m reading table tutorial in lua.org and I think if I use this method

local paints = { "paint1", "paint2", to paint 36...}

Then in the button function, “ended” phase, I assign the params to every “paint texture”, once assigned, fill the square, I would avoid loading all the textures when scene start. I also think that only the “paint texture” that the user selects when pressing the button will be loaded into texture memory. But I would like to be sure.

I would like to ask a question though, is each button going to set that square to a certain color and that’s it, or will there be more to each function, because if it is only setting a fill, then you could just make one function, and take in like an id or something, then you could concatenate the id to the file path.

Now if you are doing more with each of the 36 functions, than ignore what I said above, it is just a suggestion. :slight_smile:

Also, you said you tested with perception, did you do any FPS calculations?

I have a memTest clock, external module, from github that print FPS, texture memory and lua memory. I require it in main lua. I can not see any change when using any of the three methods.

I want to fill a square with 36 different paint textures. I have 36 buttons and 36 functions. I do not have the knowledge to make one button/function to make it all work at once. If you like to help me I will appreciate.

Alright, are the 36 button functions you use, are they similar to each other? If they are not, then we can’t make them all work from one function, but if they are we could.

For example post the code for button function 4, button function 19, and button function 34. Just as an example to verify if they are similar or not.

Yes, they are basically the same function, the only thing that changes is the square.fill and some extras. But all the buttons are in a scrollview. The button has “moved” and “ended” phase where in the “moved” phase I use it for the scrollview take focus and in the “ended” phase I play the sound of the button, move the position of two display objects (different position coordinates in each function) and use the square.fill. I’m not in my house but when I arrive I will post the code of the three functions that you ask me.

The button function:

local paint = {} local function paint1ButtonTouch( event ) if ( event.phase == "moved" ) then dy = math.abs( event.y - event.yStart ) if ( dy \> 5 ) then scrollView:takeFocus( event ) end elseif ( event.phase == "ended" ) then paint={type="image",filename="images/paint1.png"} audio.play( a\_1) select.alpha = 0 select.x = 21 select.y = 35 transition.fadeIn( select, { time=350 } ) square.fill = paint end return true end

I do not write the other functions cause they are all the same, the change are in x and y values of “select” display object and paints texture images.

Thanks in advance

DoDi

Or maybe call the paints local inside every button function, “ended” phase, works better?

I think there may be some confusion.

local paint1 = { type = "image", filename = "images/paint1.png" }

Creates a table with two string elements in it. It’s using zero texture memory.

local paint = {} paint[1] = { type = "image", filename = "images/paint1.png" paint[2] = { type = "image", filename = "images/paint2.png"

would create a table of sub-tables. Texture memory isn’t allocated until you update the “.fill” attribute.

So now the question is 36 tables more efficient than one table with 36 sub-tables. I would say it would be purely on memory consumption, the 36 individual tables would save a few bytes of memory. But Lua only allows you to have 200 local variables and using the 36 takes a chunk of those. Then you have the concept of upvalues, which are where you, inside a function reference a value at a scope higher than that function. You can only have 60 upvalues referenced in any one Lua block, so if you in your function write:

local function button( event )      if id == 1 then           square.fill = paint1      elseif id == 2 then           square.fill = paint2      else id == 3 then           square.fill = paint3      end end

Your reference to paint1, paint2 and paint3 in this example are upvalues. Since you will have 36 of them, you’ve used 36 of your 60 upvalues.  If you do a table of sub-tables, you use 1 upvalue. So from that perspective, I would suggest a table of sub-tables. Then you can use a simple index to access it. A table of sub-tables is easily put into an external module.

Rob

Thanks Rob, very well explained. Last question, is there any difference between these two methods?

local paints = { "paint1", "paint2", "paint3" } paint1 = { type = "image", filename = "images/paint1.png" } paint2 = { type = "image", filename = "images/paint2.png" } paint3 = { type = "image", filename = "images/paint3.png" }

or the one you suggest: 

local paint = {} paint[1] = { type = "image", filename = "images/paint1.png" paint[2] = { type = "image", filename = "images/paint2.png" paint[3] = { type = "image", filename = "images/paint3.png"

Well, the top one wouldn’t even work as you think it would. Paints is a table containing just three string values, and paint1, paint2 etc are standalone global tables with nothing to do with paints.

After reading and testing what is spoken in this topic I would like to carry out the code by making a table in an external module to be able to use it in the required scene but I am having scope problems.

--paint.lua local paint = {} paint[1] = { type = "image", filename = "images/paint1.png" } paint[2] = { type = "image", filename = "images/paint2.png" } paint[3] = { type = "image", filename = "images/paint3.png" } --to paint[36] return paint

but when I try to use it in scene give a local/global error

--scene1.lua local paint = require( "paint" ) local function paint1ButtonTouch( event ) if ( event.phase == "moved" ) then         dy = math.abs( event.y - event.yStart )         if ( dy \> 5 ) then    scrollView:takeFocus( event ) end elseif ( event.phase == "ended" ) then audio.play( a\_1) select.alpha = 0 select.x = 21    select.y = 35         transition.fadeIn( select, { time=350 } ) square.fill = paint.paint[1] --here is the error end return true end

The reason is I don’t know how to handle table in external module.

I think this way is the best performance using external modules.

any help?

Thanks DoDi 

@nick_sherman

I read in the forums or a tutorial, don’t remember right now, to avoid the 60 up values issue you can do the empty table.

Is something like store a bunch of variables in to one local table to make them local too, then anywhere in the code, use those variables. 

I’m right?

based on the code as you have it in paint.lua

in scene1.lua

it should be   paint[1]     not  paint.paint[1]

square.fill = paint[1]

Best of luck with your game!