PLEASE Help with big, on-going bug...

Hi guys, 

I really need your help and advice with a particular on-going issue I am experiencing to do with system memory leak and the use of modular functions.

Basically, I had a lot of coding for a level, but at the same time I wanted to use the same coding for all the levels, and so it made sense to modularise my functions (templating them, effectively) . And so I did the usual thing of putting the functions into external modules and then calling them in to my main script for the level. For example, this is what the script inside my external module might look like

local m = {} local functionInsideModule = function (obj) local functionobject = display.newImage("objectImage.png") -- here I would change some values etc obj.relevantValue = 2 return functionobject end m.functionInsideModule = functionInsideModule 

And I would then bring this into my script for Level4 like so:

local externalMod = require("external-mod") --every time I want to use that created object I know use it like this transition.to(externalMod.functionInsideModule.functionObject, {x= 100, time= 100})

However, the problem I am having, I think (because I don’t know for sure what the exact problem is so I need your help), is that with all these variables being shared between the main level scritpt and the external module, my system memory usage is going up.

However, I cannot really think of another way to do it, as it would be very helpful for me to modularise these functions, as it really helps organisation etc. if I can compartmentalise the functions, and share them between levels.

Does anyone have any advice on what can be done here? How do you modularise coding and functions, but at the same time share the objects and variables that are created within those functions between your module and your main script - without raising the system memory usage too much?

Any help you could give guys would be REAAALLLY appreciated! Thanks in advance!

Where exactly are you seeing the problem? Is performance slowing, or do you get crashes? Are you getting errors in the logs? Knowing this would help out in resolving.

There are alternatives ; there is the template design pattern - you define an abstract class (or one with dummy methods) which you then override as necessary. 

I do wonder if it might be to do with the caching of require() ; are your scenes being re-initialised properly - my understanding is that if you require() something twice it just simply re-uses it rather than actually re-initialises things, e.g. running inline code in the required file.

So you might have something like (my syntax for OOP)

local AbstractScene = BaseClass:new() function AbstractScene:getTransitionalObject() error "Abstract class" end function AbstractScene:doTransition() transition.to(self:getTransitionalObject(), { x = 100, time = 100 } end local SomeNewScene = AbstractScene:new() function SomeNewScene:getTransitionalObject() return \<some object\> end local scene = SomeNewScene:new() scene:doTransition()

There’s an extra level of abstraction here, sort of ; rather than relying on the require() to instantiate your scene, you use it to create your class (or prototype object if  you prefer) and then create a new instance out of it, which is used to do whatever, rather than working on the actual prototype itself. Each different game scene design is a new class, but each time you run it you get a new instance of the relevant class.

In practice, sometimes you have to have some sort of global or singleton :slight_smile:  That’s not really the problem , it’s minimising it and decoupling it as far as you can. There are things you just want one of sometimes :slight_smile: (like for instance bitmap images in Corona itself - so you do fourteen display.newImages() and there is only one actual copy of the image !)

If you don’t want globals, another way is to have a central broadcasting event message system - this in itself is a global :slight_smile: but it’s a controllable one, so you broadcast messages when things happen. 

So you might rather than calling a method addToScore() on a global, broadcast a message to some/all of the game objects, something like MessageBroadcast(“addToScore”, { points = 10 }). This has some advantages - you can dump the messages to see what’s going on, it can be a bit resource heavy if you overdo it. It’s easier to track multiple listeners or non-removal errors because everyone is listening to the same thing. There is a long ongoing argument when communicating between different components in apps whether you use a global, whether you have direct messages/method calls, or some sort of central repository for them.

I’m not convinced though that your memory leakage is down to the use of your template method system per se ; it seems quite sound to me. Just simply having a few globals should not increase memory significantly. It is more things like unreleased resources, circular memory allocations, creating closures and that sort of stuff

I don’t think it has anything to do with your use of modules. Rather, I think it’s a simple case that your function (wherever you decide to place it, separate module or not) is creating a display object that you don’t (seem to) track for later removal.

You create an object (via the function), record no reference of it, then assign a transition to it – but then what? Who ever removes that object? You don’t have a reference, so YOU can’t do it, nor is it created within any group anywhere, so removing its parent won’t remove it, there’s no on complete listener for the transition that might be removing it, so… looks like it remains forever, and if so it’s the “classic” Corona memory leak.

How much memory are you leaking? Does the amount correlate with the number of times that function is called?

Hi Guys, sorry about the reply, I’ve been away for last few days.

Panc Software - Hi, I’m not seeing too much of a problem at the moment (not in terms of visual performance etc anyway), but at the moment I haven’t built the levels up to the fullest extent either, so that may get worse, so I’m just a little anxious. At the moment my System Mem usage is around 0.65 - and I hear the average is between 0.5 and 1? Is that correct?

     Also, what is the average level of System Mem usage that it is ok to get to within any individual level in the storyboard (i.e. before you purge the scene and go back to the ‘level select’ screen or something) ??

Paulscottrobson - Hi, ok it’s good to know my template isn’t too bad. When I say high System Mem usage, sorry I am referring to within an individual Scene. I’m not specifically talking about the ‘carry-over’ of mem usage between scenes and the ‘level select’ screen (I haven’t even started testing that in detail yet! ) I am just talking about within an individual scene, when most level elements are being used.

    The reason I ask this question is because I noticed that when I set up the function itself in the module, my SystemMem usage didn’t increase much, but as soon as I link it back to the main Level script (by using something like m.functionInsideModule = functionInsideModule) , then SystemMem usage increases.

    Also, I just wanted to ask your opinion about the general way that I’ve set up the interplay of functions : In my main level Script, when I try and use one variable that was created in one particular module inside another module, then I need to pass the name of the module into the function. What I have done to make this more simple is that I have created a global array in my main Level (called ‘MainFunc’). After this when I create a new module I place the module into the array - e.g. MainFunc.FirstModule = require(“first-module”) After this, when I am calling a function which exists inside FirstModule but I am inside SecondModule, then I reference it like ‘MainFunc.FirstModule.RandomFunction’. 

     At the time when I did this it felt very convoluted, and it still does, but I couldn’t really see any other reasonable long-term solution around it. I needed a way to call one function from a Module which wasn’t necessarily the module it was created in, and because of scoping of variables etc., I had to create the MainFunc array so I could pass this as a global variable parameter into the various functions). It kind of seems that my MainFunc array is similar to the central message broadcasting system that you mentioned, in principle? 

davidbollinger - hi, yes apologies david I don’t think I explained the situation fully, didn’t show the whole code. There are other parts of the coding (i.e. the ‘ExitScene’ and ‘RemoveSecene’ event listeners) where I place the various objects into different object Groups,  and then perform ‘removeSelf()’ on the various objects etc. This is what you’re referring to isn’t it, when you say later removal isn’t it?

Thanks guys!

Hi Guys,

Has anyone else got any other ideas on this at all?

I wouldn’t worry too much as long as your memory usage doesn’t keep going up and up. Your method is just another way of doing it, different people prefer different approaches.

People say don’t use globals, and you shouldn’t but there are times when you need a singleton or global in your code.

Where exactly are you seeing the problem? Is performance slowing, or do you get crashes? Are you getting errors in the logs? Knowing this would help out in resolving.

There are alternatives ; there is the template design pattern - you define an abstract class (or one with dummy methods) which you then override as necessary. 

I do wonder if it might be to do with the caching of require() ; are your scenes being re-initialised properly - my understanding is that if you require() something twice it just simply re-uses it rather than actually re-initialises things, e.g. running inline code in the required file.

So you might have something like (my syntax for OOP)

local AbstractScene = BaseClass:new() function AbstractScene:getTransitionalObject() error "Abstract class" end function AbstractScene:doTransition() transition.to(self:getTransitionalObject(), { x = 100, time = 100 } end local SomeNewScene = AbstractScene:new() function SomeNewScene:getTransitionalObject() return \<some object\> end local scene = SomeNewScene:new() scene:doTransition()

There’s an extra level of abstraction here, sort of ; rather than relying on the require() to instantiate your scene, you use it to create your class (or prototype object if  you prefer) and then create a new instance out of it, which is used to do whatever, rather than working on the actual prototype itself. Each different game scene design is a new class, but each time you run it you get a new instance of the relevant class.

In practice, sometimes you have to have some sort of global or singleton :slight_smile:  That’s not really the problem , it’s minimising it and decoupling it as far as you can. There are things you just want one of sometimes :slight_smile: (like for instance bitmap images in Corona itself - so you do fourteen display.newImages() and there is only one actual copy of the image !)

If you don’t want globals, another way is to have a central broadcasting event message system - this in itself is a global :slight_smile: but it’s a controllable one, so you broadcast messages when things happen. 

So you might rather than calling a method addToScore() on a global, broadcast a message to some/all of the game objects, something like MessageBroadcast(“addToScore”, { points = 10 }). This has some advantages - you can dump the messages to see what’s going on, it can be a bit resource heavy if you overdo it. It’s easier to track multiple listeners or non-removal errors because everyone is listening to the same thing. There is a long ongoing argument when communicating between different components in apps whether you use a global, whether you have direct messages/method calls, or some sort of central repository for them.

I’m not convinced though that your memory leakage is down to the use of your template method system per se ; it seems quite sound to me. Just simply having a few globals should not increase memory significantly. It is more things like unreleased resources, circular memory allocations, creating closures and that sort of stuff

I don’t think it has anything to do with your use of modules. Rather, I think it’s a simple case that your function (wherever you decide to place it, separate module or not) is creating a display object that you don’t (seem to) track for later removal.

You create an object (via the function), record no reference of it, then assign a transition to it – but then what? Who ever removes that object? You don’t have a reference, so YOU can’t do it, nor is it created within any group anywhere, so removing its parent won’t remove it, there’s no on complete listener for the transition that might be removing it, so… looks like it remains forever, and if so it’s the “classic” Corona memory leak.

How much memory are you leaking? Does the amount correlate with the number of times that function is called?

Hi Guys, sorry about the reply, I’ve been away for last few days.

Panc Software - Hi, I’m not seeing too much of a problem at the moment (not in terms of visual performance etc anyway), but at the moment I haven’t built the levels up to the fullest extent either, so that may get worse, so I’m just a little anxious. At the moment my System Mem usage is around 0.65 - and I hear the average is between 0.5 and 1? Is that correct?

     Also, what is the average level of System Mem usage that it is ok to get to within any individual level in the storyboard (i.e. before you purge the scene and go back to the ‘level select’ screen or something) ??

Paulscottrobson - Hi, ok it’s good to know my template isn’t too bad. When I say high System Mem usage, sorry I am referring to within an individual Scene. I’m not specifically talking about the ‘carry-over’ of mem usage between scenes and the ‘level select’ screen (I haven’t even started testing that in detail yet! ) I am just talking about within an individual scene, when most level elements are being used.

    The reason I ask this question is because I noticed that when I set up the function itself in the module, my SystemMem usage didn’t increase much, but as soon as I link it back to the main Level script (by using something like m.functionInsideModule = functionInsideModule) , then SystemMem usage increases.

    Also, I just wanted to ask your opinion about the general way that I’ve set up the interplay of functions : In my main level Script, when I try and use one variable that was created in one particular module inside another module, then I need to pass the name of the module into the function. What I have done to make this more simple is that I have created a global array in my main Level (called ‘MainFunc’). After this when I create a new module I place the module into the array - e.g. MainFunc.FirstModule = require(“first-module”) After this, when I am calling a function which exists inside FirstModule but I am inside SecondModule, then I reference it like ‘MainFunc.FirstModule.RandomFunction’. 

     At the time when I did this it felt very convoluted, and it still does, but I couldn’t really see any other reasonable long-term solution around it. I needed a way to call one function from a Module which wasn’t necessarily the module it was created in, and because of scoping of variables etc., I had to create the MainFunc array so I could pass this as a global variable parameter into the various functions). It kind of seems that my MainFunc array is similar to the central message broadcasting system that you mentioned, in principle? 

davidbollinger - hi, yes apologies david I don’t think I explained the situation fully, didn’t show the whole code. There are other parts of the coding (i.e. the ‘ExitScene’ and ‘RemoveSecene’ event listeners) where I place the various objects into different object Groups,  and then perform ‘removeSelf()’ on the various objects etc. This is what you’re referring to isn’t it, when you say later removal isn’t it?

Thanks guys!

Hi Guys,

Has anyone else got any other ideas on this at all?

I wouldn’t worry too much as long as your memory usage doesn’t keep going up and up. Your method is just another way of doing it, different people prefer different approaches.

People say don’t use globals, and you shouldn’t but there are times when you need a singleton or global in your code.