Quick Links: Gideros Home | Download Gideros | Developer Guide
Event dispatcher causes memory leak
  • Yan +1 -1
    Member
    anonymous/lambda event usage causes leak
    b:dispatchEvent(Event.new("myevent"))


    every time this code runs, memory usage grows. checked via code

    Leak
    self:addEventListener(Event.KEY_DOWN, function(event) if event.keyCode == KeyCode.UP then self.controls:dispatchEvent(Event.new("shoot")) end end)


    No leak
    local shoot = Event.new("shoot")
    self:addEventListener(Event.KEY_DOWN, function(event) if event.keyCode == KeyCode.SPACE then self.controls:dispatchEvent(shoot) end end)


    Gideros v.2017.4.1
    stage:addEventListener(Event.ENTER_FRAME, function() print("MemUsage: ", math.ceil(collectgarbage("count")), "TextureUsage:", application:getTextureMemoryUsage()) end, e)
  • Ok just a guess.
    For the leak version;
    Every time this code runs it is generating a new object from Event.new function so it is consuming memory. You can try like this if you are near computer to see if my scenario is correct or not. You can force gideros to collect garbage directly, Maybe it will help.
    self:addEventListener(Event.KEY_DOWN, function(event) if event.keyCode == KeyCode.UP then self.controls:dispatchEvent(Event.new("shoot")) end end)
    collectgarbage()

    For the No leak version
    In this case you are using the local variable shoot for the Event object which is garbage collected by Gideros automatically after it is used.

    But as i said those are only my guesses :-?

  • Hi @Yan
    Are you using sceneManager Class???
    'Cos when you change scene it destroy scene, so if some variables or functions aren't inside function class like a local or "self." ... it can cause memory leaks

    and yes like you saids Event increase your memory but if you use correctly sceneManager or collectgarbage() I don't believe then you have a lot problems, unless you are using events very intensively but in this case I follow suggestion of @talis

    For example when I use my class Box = Core.class(Sprite) it create boxes draggable for Box2D on the main class so:
    function Box:onMouseDown(event)
    if self:hitTestPoint(event.x, event.y) then
    self.isFocus = true
    self.x0, self.y0 = event.x, event.y
    --============
    self:dispatchEvent(Event.new("jointDown"))
    --============
    event:stopPropagation()
    end
    end
    --
    function Box:onMouseMove(event)
    if self.isFocus then
    self.dx = event.x - self.x0
    self.dy = event.y - self.y0
     
    self:setX(self:getX() + self.dx)
    self:setY(self:getY() + self.dy)
     
    self.x0, self.y0 = event.x, event.y
    --============
    self:dispatchEvent(Event.new("jointMove"))
    --============
    event:stopPropagation()
    end
    end
     
    function Box:onMouseUp(event)
    if self.isFocus then
    self.isFocus = false
    self:dispatchEvent(Event.new("jointUp"))
    -------------------
    collectgarbage() --<-- only here because collectgabage can affect performance of your applications
    -------------------
    event:stopPropagation()
    end
    end

    so the key is to know where you must put collectgarbage() because it can affect performance of your application
  • SinisterSoftSinisterSoft +1 -1 (+3 / -0 )
    Maintainer
    I put this at the bottom of my main.lua
    collectgarbage("setstepmul",1000)
    collectgarbage()


    Then I put this in my main game loop event:
    	collectgarbage("step")
    --print(collectgarbage("count")*1024)


    I uncomment the print statement and run then program. I adjust the 1000 figure up or down until the memory usage balances out over several seconds. Once balanced I comment out the print statement and I then know that garbage collection won't cause any sudden drops in the frame rate.
  • Once balanced I comment out the print statement and I then know that garbage collection won't cause any sudden drops in the frame rate.


    Nice suggestion @SinisterSoft I'm going to use your method in my future apps or updates ;)

  • Yan +1 -1
    Member

    I put this at the bottom of my main.lua

    collectgarbage("setstepmul",1000)
    collectgarbage()


    Then I put this in my main game loop event:
    	collectgarbage("step")
    --print(collectgarbage("count")*1024)


    I uncomment the print statement and run then program. I adjust the 1000 figure up or down until the memory usage balances out over several seconds. Once balanced I comment out the print statement and I then know that garbage collection won't cause any sudden drops in the frame rate.


    I sureley have fps drop after collectgrbage() so I dont think its a good idea to call cg after each button push. Or in game loop.
  • Yan +1 -1
    Member
    talis said:

    Ok just a guess.
    For the leak version;
    Every time this code runs it is generating a new object from Event.new function so it is consuming memory. You can try like this if you are near computer to see if my scenario is correct or not. You can force gideros to collect garbage directly, Maybe it will help.

    self:addEventListener(Event.KEY_DOWN, function(event) if event.keyCode == KeyCode.UP then self.controls:dispatchEvent(Event.new("shoot")) end end)
    collectgarbage()

    For the No leak version
    In this case you are using the local variable shoot for the Event object which is garbage collected by Gideros automatically after it is used.

    But as i said those are only my guesses :-?



    Yes it is right, every time I dispatch event, I need to think about event object that need to be garbage collected or distroyed. Or I should make an event pool and reuse created event. I wanted just notice this is not convient approach.
  • @Yan I step through the garbage collect - doing a little at a time (see "setstepmul",1000 ). My game is none-stop with no breaks so by doing this I stop a massive pause when it would reach a limit. I did some tests a while back and the time taken for the collect this way was negligible.

    My game btw has tons going on and runs at a constant 60hz even on a slow device.

    http://www.sinistersoft.com/RetroStar/gideros.html
  • Yan +1 -1
    Member

    @Yan I step through the garbage collect - doing a little at a time (see "setstepmul",1000 ). My game is none-stop with no breaks so by doing this I stop a massive pause when it would reach a limit. I did some tests a while back and the time taken for the collect this way was negligible.

    My game btw has tons going on and runs at a constant 60hz even on a slow device.

    http://www.sinistersoft.com/RetroStar/gideros.html



    Thanks 4 explanation ! Well so 1000 is times or bytes ? can you explain more how to achieve this number for my case ?
  • Try it with 1000, if you see memory usage increasing and not going down then increase the number. If you see it always constant then try lowering it until you see it start to rise, then go back a step.
  • Yan +1 -1
    Member

    Try it with 1000, if you see memory usage increasing and not going down then increase the number. If you see it always constant then try lowering it until you see it start to rise, then go back a step.



    Ty ill try, so I doubt its the iterations option ?


Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Login with Facebook Sign In with OpenID

In this Discussion

Top Posters