Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Memory Leak Issue
Started by crssmn Nov 24 2010 11:35 AM

- - - - -
35 replies to this topic
[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

I'm try to any number of objects and remove them upon a collision. I find that the remove function isn't completely clearing the memory causing a memory leak, but I cannot figure out why. Any help is appreciated, thanks in advance.


local physics = require("physics")
physics.start()
physics.setGravity( 0, 0 )
 
local score = 0
 
local x = 25
 
local background = display.newImage("background.png")
 
scoreTextfield = display.newText( " " .. score, 280, 105, nil, 14 )
scoreTextfield:setTextColor( 0, 0, 0, 255 )
 
scoreTextfield.text = " " .. score
 
collectgarbage("collect")
score = "System Memory : " .. collectgarbage("count")
scoreTextfield.text = " " .. score
 
local bar = display.newImage( "bar.png" )
bar.x = 170 ; bar.y = 350
physics.addBody( bar, "static", { density=2.9, friction=0.0, bounce = 0 } )
 
local function randomBall ()
 
if x < 3000 then
                        
        local imageBall = display.newImage( "ball.png" )
                                        
        local randomPos = math.random
                                
        imageBall.x = 10 + randomPos( 300 ); imageBall.y = -20
                                        
        physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )
 
        imageBall:setLinearVelocity( 0, 600 )
        
        imageBall:addEventListener( "collision", imageBall )
        
        collectgarbage("collect")
        score = "System Memory : " .. collectgarbage("count")
        scoreTextfield.text = " " .. score
        
        local function onLocalCollision( self, event )
                                
        if ( imageBall.x ) then                    
                                                                
                if ( imageBall.y > 300 ) then                                                   
                                                                
                imageBall:removeEventListener( "collision", imageBall )
                imageBall:removeSelf()
                imageBall = nil
                               
                collectgarbage("collect")
                score = "System Memory : " .. collectgarbage("count")
                scoreTextfield.text = " " .. score
                                
                end
                        
        end
        
        end
 
        imageBall.collision = onLocalCollision
        
end
 
end
 
y = 30
 
local timberBall = timer.performWithDelay( x, randomBall, y )

uid: 10903 topic_id: 3987 reply_id: 303987


[TOPIC: post.html]
#2

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

Updated code, but I still get a memory leak.


local physics = require("physics")
physics.start()
physics.setGravity( 0, 0 )
 
local score = 0
 
local x = 50
 
scoreTextfield = display.newText( " " .. score, 200, 105, nil, 14 )
scoreTextfield:setTextColor( 255, 255, 255, 255 )
 
scoreTextfield.text = " " .. score
 
collectgarbage("collect")
score = "System Memory : " .. collectgarbage("count")
scoreTextfield.text = " " .. score
 
local bar = display.newRect(  0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, "static", { density=2.9, friction=0.0, bounce = 0 } )

local function onLocalCollision( obj, event )
                                
	if ( obj.x ) then                    
                                                                
		if ( obj.y > 315) then                                                   
                                                                
			obj:removeSelf()
                                
		end
                        
	end
        
end
 
local function randomBall ()
 
if x < 3000 then
       
        local randomPos = math.random
       
        local imageBall = display.newRect(  randomPos(300), -20, 30, 30 )
        imageBall:setFillColor ( 255, 255, 255 )
                                        
        physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )
 
        imageBall:setLinearVelocity( 0, 600 )
        
        imageBall:addEventListener( "collision", imageBall )
 
        imageBall.collision = onLocalCollision  
 
end
 
end
 
y = 14
 
local timerBall = timer.performWithDelay( x, randomBall, y )
 
local function memCheck ()
 
        collectgarbage("collect")
        score = "System Memory : " .. collectgarbage("count")
        scoreTextfield.text = " " .. score
 
end
 
local timerCheck = timer.performWithDelay( 3000, memCheck, 1 )

uid: 10903 topic_id: 3987 reply_id: 12279


[TOPIC: post.html]
#3

erpy

[GLOBAL: userInfoPane.html]
erpy
  • Contributor

  • 154 posts
  • Corona SDK

I'd firstly verify that the removeSelf() is actually reached.
Put a print there and check if it's really called as expected.
uid: 5750 topic_id: 3987 reply_id: 12293


[TOPIC: post.html]
#4

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

Yes it seems to reach the remove.


local physics = require("physics")
physics.start()
physics.setGravity( 0, 0 )
 
local score = 0
 
local x = 50
 
scoreTextfield = display.newText( " " .. score, 200, 105, nil, 14 )
scoreTextfield:setTextColor( 255, 255, 255, 255 )
 
scoreTextfield.text = " " .. score
 
collectgarbage("collect")
score = "System Memory : " .. collectgarbage("count")
scoreTextfield.text = " " .. score
 
local bar = display.newRect(  0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, "static", { density=2.9, friction=0.0, bounce = 0 } )

local function onLocalCollision( obj, event )
                                
	if ( obj.x ) then                    
                                                                
		if ( obj.y > 315) then                                                   
            print("removed")                                                    
			obj:removeSelf()
                                
		end
                        
	end
        
end
 
local function randomBall ()
 
if x < 3000 then
       
        local randomPos = math.random
       
        local imageBall = display.newRect(  randomPos(300), -20, 30, 30 )
        imageBall:setFillColor ( 255, 255, 255 )
                                        
        physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )
 
        imageBall:setLinearVelocity( 0, 600 )
        
        imageBall:addEventListener( "collision", imageBall )
 
        imageBall.collision = onLocalCollision  
 
end
 
end
 
y = 14
 
local timerBall = timer.performWithDelay( x, randomBall, y )
 
local function memCheck ()
 
        collectgarbage("collect")
        score = "System Memory : " .. collectgarbage("count")
        scoreTextfield.text = " " .. score
 
end
 
local timerCheck = timer.performWithDelay( 3000, memCheck, 1 )

uid: 10903 topic_id: 3987 reply_id: 12294


[TOPIC: post.html]
#5

erpy

[GLOBAL: userInfoPane.html]
erpy
  • Contributor

  • 154 posts
  • Corona SDK

I'm not very into Game Edition, but, don't you need to remove the body as well ?
You're currently removing graphics only.
uid: 5750 topic_id: 3987 reply_id: 12295


[TOPIC: post.html]
#6

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

According to the resources at http://developer.anscamobile.com/content/game-edition-physics-bodies

"A display object that has physical properties can be deleted in the normal way, using object:removeSelf(). It will be automatically removed from both the visible screen and the physical simulation."
uid: 10903 topic_id: 3987 reply_id: 12297


[TOPIC: post.html]
#7

erpy

[GLOBAL: userInfoPane.html]
erpy
  • Contributor

  • 154 posts
  • Corona SDK

So, in theory, if you try to remove the body as well, after removing the graphic object, you should get an error saying the phisical object is nil... I'd try that.

You might also want to check in the current bugs. This might be an open one.
uid: 5750 topic_id: 3987 reply_id: 12300


[TOPIC: post.html]
#8

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

I think the removeSelf function is supposed to remove the body, their is no physics.removeBody function other than removeSelf as far as I can tell.

I'll check the bugs.
uid: 10903 topic_id: 3987 reply_id: 12301


[TOPIC: post.html]
#9

erpy

[GLOBAL: userInfoPane.html]
erpy
  • Contributor

  • 154 posts
  • Corona SDK

As from the Docs, it uses the same method:
http://developer.anscamobile.com/content/game-edition-physics-bodies#Destroying_bodies
uid: 5750 topic_id: 3987 reply_id: 12305


[TOPIC: post.html]
#10

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

Are you suggesting to use:

if ( obj.y > 315) then 
	obj.parent:remove( obj )
        print("removed")                    
end

?

I still get a leak if I do.
uid: 10903 topic_id: 3987 reply_id: 12306


[TOPIC: post.html]
#11

erpy

[GLOBAL: userInfoPane.html]
erpy
  • Contributor

  • 154 posts
  • Corona SDK

Does it change anything if you nil out the obj ?

local function onLocalCollision( obj, event )                                        if ( obj.x ) then                                                                                                    if ( obj.y > 315) then                                                                           print("removed")                                                                            obj:removeSelf()                        obj = nil                                                end                                end        end


Edit:
Also, check the numChildren in stage... see how it changes...if it grows etc.
uid: 5750 topic_id: 3987 reply_id: 12307


[TOPIC: post.html]
#12

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

Nil-ing out makes a tiny difference.

The numChildren counts check out fine.
uid: 10903 topic_id: 3987 reply_id: 12309


[TOPIC: post.html]
#13

erpy

[GLOBAL: userInfoPane.html]
erpy
  • Contributor

  • 154 posts
  • Corona SDK

I gave a better look at your function, my question is, how can you be sure you're actually leaking memory ?

When your memoryCheck function starts, do you expect all memory to be released ? And if yes, all the 14 balls collided and met the condition within your onLocalCollision function ?

Clearly, if not all the 14 balls collided with such conditions, not all of them are released - and after 3 seconds since start.
uid: 5750 topic_id: 3987 reply_id: 12311


[TOPIC: post.html]
#14

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

You can set the memoryCheck to run a number of times and check the value over time. So the last iteration happens well after the last collision.

Then run it again with a larger y value and you'll find that the last iteration reads a larger memory count.

[code=auto:0]

local physics = require("physics")
physics.start()
physics.setGravity( 0, 0 )

local x = 50

collectgarbage("collect")
print("System Memory : " .. collectgarbage("count"))

local bar = display.newRect( 0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, "static", { density=2.9, friction=0.0, bounce = 0 } )

local function onLocalCollision( obj, event )

if ( obj.x ) then

if ( obj.y > 315) then
obj:removeSelf()
obj = nil

end

end

end

local function randomBall ()

if x < 3000 then

local randomPos = math.random

local imageBall = display.newRect( randomPos(300), -20, 30, 30 )
imageBall:setFillColor ( 255, 255, 255 )

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( "collision", imageBall )

imageBall.collision = onLocalCollision

end

end

y = 10

local timerBall = timer.performWithDelay( x, randomBall, y )

local function memCheck ()

collectgarbage("collect")
print("System Memory : " .. collectgarbage("count"))

end

local timerCheck = timer.performWithDelay( 3000, memCheck, 3 )
uid: 10903 topic_id: 3987 reply_id: 12312


[TOPIC: post.html]
#15

erpy

[GLOBAL: userInfoPane.html]
erpy
  • Contributor

  • 154 posts
  • Corona SDK

Ok, but I don't know how much that matters. I was pointing out that you're not in a "safe" environment in order to call that a memory leak.

If you can't find this issue among the current bugs, I'd suggest creating a small test-bed with physics, where you know exactly "what and when" once you remove something and exactly what you expect to happen after you check the memory.

For instance, I'd let bodies fall with gravity and once they reached a max Y coord (ground) I'd remove them.
After the simulation terminates I'd check memory and see if anything's still in memory despite ALL bodies were removed for sure - i.e. if stage.numChildren is the same as before ALL bodies were created.
uid: 5750 topic_id: 3987 reply_id: 12314


[TOPIC: post.html]
#16

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

Well what I was doing was using this code to create a tetris like game where the player removes the objects before they hit the bottom of the screen. The loop runs infinitely unless an object hits the bottom at which time the loop ends.

The issue I was getting was that if I run the loop infinitely I get major memory loss on the device after a few hundred objects.

So I devised this code just to test the object removal on event.
uid: 10903 topic_id: 3987 reply_id: 12315


[TOPIC: post.html]
#17

jmp909

[GLOBAL: userInfoPane.html]
jmp909
  • Corona Geek

  • 1,328 posts
  • Corona SDK

dont know if this is any use but this is what happens to your object during collision (I'm using a print_r function, if you need it i can give you the code)

----- beginning of collision - print_r(obj)table: 0x2c08e50 {  [_proxy] => userdata: 0x2c18cb4  [_functionListeners] => table: 0x2c08e50 {                            [collision] => table: 0x2c0d050 {                                             [1] => function: 0x2663b20                                           }                          }  [_dispatchingEventName] => "collision"  [collision] => function: 0x2663b20  [_class] => table: 0x2c08e50 {                [removeBehavior] => function: 0x264cf00                [initProxy] => function: 0x264cd40                [hasBehavior] => function: 0x264ce80                [addBehavior] => function: 0x264cea0                [__index] => table: 0x264cd20 {                               *table: 0x264cd20                             }              }}----- after obj:removeSelf(), print_r(obj) --------table: 0x2c08e50 {  [_functionListeners] => table: 0x2c08e50 {                            [collision] => table: 0x2c0d050 {                                             [1] => function: 0x262ac90                                           }                          }  [_dispatchingEventName] => "collision"} ----- after obj = nil, print_r(obj) ---- nil

uid: 6645 topic_id: 3987 reply_id: 12326


[TOPIC: post.html]
#18

jmp909

[GLOBAL: userInfoPane.html]
jmp909
  • Corona Geek

  • 1,328 posts
  • Corona SDK

also change your memCheck timer to

local timerCheck = timer.performWithDelay( 100, memCheck, -1 )


eventually it stabilizes to a consistent value, but the more objects you had, the higher this value will be. which to me would confirm a leak i think

with 100 objects

(note the second number is from gcinfo http://lua.gts-stolberg.de/en/Basis.php#gcinfo() )

startup.. System Memory : 68.5634765625 / 68after collectgarbage before display items added.. System Memory : 60.662109375 / 60after bar & physics added . System Memory : 61.255859375 / 61-- System Memory : 60.595703125 / 60System Memory : 61.126953125 / 61System Memory : 61.751953125 / 61System Memory : 62.283203125 / 62System Memory : 62.736328125 / 62System Memory : 63.166015625 / 63System Memory : 63.384765625 / 63System Memory : 63.603515625 / 63......System Memory : 86.1357421875 / 86System Memory : 86.3544921875 / 86System Memory : 85.330078125 / 85System Memory : 85.017578125 / 85System Memory : 84.705078125 / 84System Memory : 84.392578125 / 84System Memory : 83.7314453125 / 83System Memory : 83.7080078125 / 83 -- ended here..stabilizesSystem Memory : 83.7080078125 / 83System Memory : 83.7080078125 / 83System Memory : 83.7080078125 / 83System Memory : 83.7080078125 / 83System Memory : 83.7080078125 / 83System Memory : 83.7080078125 / 83

uid: 6645 topic_id: 3987 reply_id: 12327


[TOPIC: post.html]
#19

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

Can you clarify what your first post means? That's over my head.

I changed my memcheck function to yours and got similar results so further confirmation of a leak.
uid: 10903 topic_id: 3987 reply_id: 12331


[TOPIC: post.html]
#20

jmp909

[GLOBAL: userInfoPane.html]
jmp909
  • Corona Geek

  • 1,328 posts
  • Corona SDK

print_r iterates through any object and lists anything it contains. those functions/tables you are seeing are added to the object as part of corona's internal event management. i wouldnt worry about it, you can see it all disappears when you set your object to nil. but the memory leak youre identifying still seems to exist

it was partly more of a check for ansca to say if there is a memory leak somewhere, maybe it's because their internal event system etc is still keeping a reference to the object memory (eg in an internal global event table etc) I couldnt say. I dont know how the internals work

j
uid: 6645 topic_id: 3987 reply_id: 12332


[TOPIC: post.html]
#21

jmp909

[GLOBAL: userInfoPane.html]
jmp909
  • Corona Geek

  • 1,328 posts
  • Corona SDK

FYI... print_r function...

function print_r ( t )         local print_r_cache={}        local function sub_print_r(t,indent)                if (print_r_cache[tostring(t)]) then                        print(indent.."*"..tostring(t))                else                        print_r_cache[tostring(t)]=true                        if (type(t)=="table") then                                for pos,val in pairs(t) do                                        if (type(val)=="table") then                                                print(indent.."["..pos.."] => "..tostring(t).." {")                                                sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))                                                print(indent..string.rep(" ",string.len(pos)+6).."}")                                        elseif (type(val)=="string") then                                                print(indent.."["..pos..'] => "'..val..'"')                                        else                                                print(indent.."["..pos.."] => "..tostring(val))                                        end                                end                        else                                print(indent..tostring(t))                        end                end        end        if (type(t)=="table") then                print(tostring(t).." {")                sub_print_r(t,"  ")                print("}")        else                sub_print_r(t,"  ")        end        print()end
uid: 6645 topic_id: 3987 reply_id: 12333


[TOPIC: post.html]
#22

jmp909

[GLOBAL: userInfoPane.html]
jmp909
  • Corona Geek

  • 1,328 posts
  • Corona SDK

here is a simpler example. no collisions. take out the line physics.addBody(ball) and the memory leak goes away. otherwise the memory usage gradually counts up

local physics=require("physics")local rnd = math.randomphysics.start()physics.setGravity(0,0)local function removeBall(obj)obj:removeSelf()endlocal function addBall()	local ball = display.newCircle(rnd(200)+50, rnd(200)+50, rnd(50)+5)	ball:setFillColor(128,128,128)	physics.addBody(ball)	transition.to(ball, {time=400, alpha=0, onComplete=removeBall})endlocal function memCheck (event)collectgarbage("collect")print("System Memory : "..collectgarbage("count"))endlocal timerBall = timer.performWithDelay(100, addBall, -1) local timerCheck = timer.performWithDelay( 50, memCheck, -1 )
uid: 6645 topic_id: 3987 reply_id: 12335


[TOPIC: post.html]
#23

crssmn

[GLOBAL: userInfoPane.html]
crssmn
  • Contributor

  • 285 posts
  • Corona SDK

Do you think there's a solution to this or is it a bug?
uid: 10903 topic_id: 3987 reply_id: 12336


[TOPIC: post.html]
#24

jmp909

[GLOBAL: userInfoPane.html]
jmp909
  • Corona Geek

  • 1,328 posts
  • Corona SDK

ansca to confirm bug i think there. my example is simple enough to check whether that memory change is expected and be able to explain why if it is.

uid: 6645 topic_id: 3987 reply_id: 12337


[TOPIC: post.html]
#25

dweezil

[GLOBAL: userInfoPane.html]
dweezil
  • Contributor

  • 568 posts
  • Corona SDK

Shouldn't you also do

obj=nil

after

obj:removeSelf()

uid: 9371 topic_id: 3987 reply_id: 12344



[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]