Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Sprite inheritance and memory managment — Gideros Forum

Sprite inheritance and memory managment

RusfighterRusfighter Member
edited April 2014 in General questions
Hello guys,

I am starting my first game with gideros and have issue one problem so far.

It is about memory managment of inheritance class of Sprite object
It is not been cleaned when the objects are removed and i do not understand what the cause is!

My code:

[CODE]
EnemyObj = Core.class(Sprite);
function EnemyObj:init()
--self.speed = 1;
self:addEventListener(Event.ENTER_FRAME, self.update, self)
end

function EnemyObj:spawn()
self:setPosition(_W+_trX, RAND(0-_trY, _H+_trY))
end

function EnemyObj:destroy()
self:removeFromParent();
self = nil
end

function EnemyObj:update(event)
local x = self:getX();
self:setX(x - 5);
if (x < -200) then
self:spawn();
self:destroy();
end
end

Rocket = Core.class(EnemyObj);
function Rocket:init()
local texture = Texture.new("images/icons/rocket.png",true);
local bitmap = Bitmap.new(texture);
--self.speed = 5;
bitmap:setAnchorPoint(0.5,0.5);
bitmap:setRotation(180);

self:addChild(bitmap);
self:spawn();
end

Pillar = Core.class(EnemyObj);
function Pillar:init()

end
[/CODE]

and on touch i call: stage:addChild(Rocket.new())

But when the destroy function is called, the memory is not been cleaned. The object is removed from stage but still exists somehow?

Does anyone have an idea what could be wrong?

Comments

  • eezingeezing Member
    edited April 2014
    If the following are true:

    - You're not manually collecting garbage
    - Memory usage is below amount required to trigger automatic collecting

    then you won't see a reduction in memory usage.
  • Even if i collectgarbage(); the event EnemyObj:update(event) is still triggered on enterframe, but it needs to be removed since the object self is also removed...


  • RusfighterRusfighter Member
    edited April 2014
    Hmm somehow if i spawn many objects , there is always 1 instance of the EnemyObj left...

    Could someone explain?

    Also please explain when the garbagecollector cleans automatically?

  • ar2rsawseenar2rsawseen Maintainer
    edited April 2014
    lua cleans garbage in cycle when internally it determined that it needs to

    you may try to force it by calling collectgarbage() multiple times in a row, still it probably won't happen immediately.

    So it is ok to have something in the memory while there is enough memory.

    And here is a way to detect when your instance is being collected:

    http://giderosmobile.com/forum/discussion/comment/12334#Comment_12334

    So if most of the instance get collected and some of them are left, it is ok. They will be collected eventually.

    But when you create lots of instances and none of them getting collected, then you have a problem (a reference that keeps them)

    And actually the fact that 1 instance does not get collected could tell also that you are keeping an external reference to it (like a property of the scene or global variable).
  • Thanks for the info.

    The problem is when for example i create 500 Rocket object at the same time and after some time the destroy method&collectgarbage is called on all those 500 object, there is still one left somehow and will eventually trigger ONE enterframe event.

    My conclusion is that there always 1 instance of rocket left somehow?
  • ar2rsawseenar2rsawseen Maintainer
    @Rusfighter yes the fact that it is exactly 1 instance seems really odd.

    Are you sure you are not like making global variable accidentally instead of local, as:
    local rocket
    for i = 1, 500 do
        rocket = Rocket.new()
    end
    will work ok, until you comment out
    --local rocket
    then you will leave last rocket reference in global variable, thus it won't be garbage collected
  • Hmm i do not create a variable at all, i just create it this way:

    for i=1, 500 do
    self:addChild(Rocket.new()); -- self is a scene sprite
    end
  • You can just execute this code: (your own image)

    whenever all the objects are removed, one enterframe event still exists....


    Maybe it is duo the inheritance gideros creates? So it always create one object of "EnemyObj"
    lua
    lua
    test.lua
    943B
  • ar2rsawseenar2rsawseen Maintainer
    Yes true, I simplified the example to achieve same result and will forward it to our CTO for feedback :)
    local total = 0
     
    Rocket = Core.class(Sprite);
    function Rocket:init()
    	total = total + 1
    	self.proxy = newproxy(true)
    	getmetatable(self.proxy).__gc = function() 
    		total = total - 1
    		print("collected", total, stage:getNumChildren())
    	end
    	Timer.delayedCall(1, function()
    		self:destroy()
    	end)
    end
     
    function Rocket:destroy()
        self:removeFromParent();
        self = nil
        collectgarbage();
    end
     
    for i=1, 500 do
    	stage:addChild(Rocket.new(i)); -- self is a scene sprite
    end
  • So what should i do now? Dispatch the Enterframe event manually?
  • ar2rsawseenar2rsawseen Maintainer
    Why? Removing enterframe does the work, doesn't it?

    It is always suggested to remove enterframe events, as they usually can be most consuming ones, remove them as soon as you don't need them.

    Other approach would be creating one single enter frame loop, and creating Rocket:step method to move it and call for each rocket on each enter frame. This way you have also an advantage of pausing the game, by simply putting single check in enter frame in single event.
  • hmmm you are right, did not thought about pausing the game...

    It is hard to pause if you do not cache those objects then hehehe
Sign In or Register to comment.