Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Event dispatcher causes memory leak — Gideros Forum

Event dispatcher causes memory leak

YanYan Member
edited September 2017 in Bugs and issues
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)
vk.com/yan_alex

Comments

  • talistalis Guru
    edited September 2017
    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 :-?

  • HubertRonaldHubertRonald Member
    edited September 2017
    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
  • 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.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+3 / -0 )Share on Facebook
  • 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 ;)

  • YanYan Member
    edited September 2017
    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.
    vk.com/yan_alex
  • YanYan Member
    edited September 2017
    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.
    vk.com/yan_alex
  • SinisterSoftSinisterSoft Maintainer
    edited September 2017
    @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
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • @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 ?
    vk.com/yan_alex
  • 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.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • 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 ?


    vk.com/yan_alex
Sign In or Register to comment.