Object Oriented Function Memory Leak

We have a function in module 1 - M:animation. Each time it is called, the framerate is slowed and Lua memory increases. After a minute the framerate has reduced from 60 to 1 or 2 frames and Lua memory continues to increase. Changing the Composer scene doesn’t resolve the framerate or return the Lua memory.

After some testing, it seems the leak is compunding each time M:animation is called which (after some testing) might be traced to that part of the function which declares local variables with data associated to the passed in object e.g. local skeleton = self.skeleton
 

function M:animation (params) local params = params or {} local skeleton = self.skeleton local root = self.root local stateData = self.stateData local state = self.state local name = self.name -- rest of function -- etc end

Later in module 1 are event states such as onStart, onEnd, onComplete. An event is dispatched to a listener in scene1 when the state of the passed in object triggers onComplete.

-- In module 1 state.onComplete = function (trackIndex, loop) --loopCount Runtime:dispatchEvent( {name="animLoop", tag=obj.name} ) end

Then in scene 1, obj:animation is called again from animLoop:
 

 function M:animLoop (event) local event = event local name = event.tag local state = {} obj[name].spine:animation( {onComplete="animLoop", sequence=loop[randPage] }) end end

And the cycle continues like this after each animation completes (in around 3 or 4 second lengths).

The object being created uses Spine to assign special Spine related states and the animation function uses Spine related calls.

I can post more code. Or is this enough to understand how memory might typically compound in an object oriented function like this being continually called?
 

Without seeing more of the code, my guess would be that the onComplete=“animLoop” which I think corresponds to the state.onComplete function, is being called twice somehow. This triggers the M:animation function to be called twice, so then you have onComplete being called 4 times, then 8 etc etc.  

This is just guesswork though, based on what you’ve shown so far and things that have happened to me in the past.

@Alan - many thanks for taking a look. Using print statements suggest M:animation is only called once each time.

But yes, I’ve also encountered things being called more than once in the past which I traced to the event.phase of object event listeners. But in this case the eventListener which is calling M:animation is a Runtime listener so there are no phases.

Still unresolved…

If anyone would like to bug test this issue, I’ve collected an example project:

https://dl.orangedox.com/fwtujtJVvpG2Ey8npr/spineTrigger.zip

This one creates 6 Spine dragons and sets their animations off. When they each trigger onComplete, they call a function which changes the name of the animation and sends it back into the animation function.

There is a performance function which displays framerate and luaMem. You’ll see this quickly degrade from 60fps down to 1 fps. The memory continues to balloon. So something is compounding somewhere each time the animation function is called. I would have blamed the global nature of Spine but it might be something more or less straight forward…

Also there is no resource drain if you setup a test condition that plays animations within onComplete e.g.

state.onComplete = function (trackIndex, loop)
    state:addAnimationByName( data )
end

The drain only occurs when you call the animation function.

Any ideas?

Thanks - this issue was traced to timers in a quasi recursive function.

Without seeing more of the code, my guess would be that the onComplete=“animLoop” which I think corresponds to the state.onComplete function, is being called twice somehow. This triggers the M:animation function to be called twice, so then you have onComplete being called 4 times, then 8 etc etc.  

This is just guesswork though, based on what you’ve shown so far and things that have happened to me in the past.

@Alan - many thanks for taking a look. Using print statements suggest M:animation is only called once each time.

But yes, I’ve also encountered things being called more than once in the past which I traced to the event.phase of object event listeners. But in this case the eventListener which is calling M:animation is a Runtime listener so there are no phases.

Still unresolved…

If anyone would like to bug test this issue, I’ve collected an example project:

https://dl.orangedox.com/fwtujtJVvpG2Ey8npr/spineTrigger.zip

This one creates 6 Spine dragons and sets their animations off. When they each trigger onComplete, they call a function which changes the name of the animation and sends it back into the animation function.

There is a performance function which displays framerate and luaMem. You’ll see this quickly degrade from 60fps down to 1 fps. The memory continues to balloon. So something is compounding somewhere each time the animation function is called. I would have blamed the global nature of Spine but it might be something more or less straight forward…

Also there is no resource drain if you setup a test condition that plays animations within onComplete e.g.

state.onComplete = function (trackIndex, loop)
    state:addAnimationByName( data )
end

The drain only occurs when you call the animation function.

Any ideas?

Thanks - this issue was traced to timers in a quasi recursive function.