A memory leak when removing and adding an image sequencely?

29 replies [Last post]
ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

The following code removes and adds an image to the screen (when the blue button is pressed).
It also prints memory usage to the terminal.

Looks like memory is increasing on every press, although the image is removed and dereferenced (lines 36-37)...
Another strange thing is that if you set image scale to be 0.25 (just un-remark lines 43-44), memory seems to stay the same...

Is there a memory leak here or is it a problem in the collectgarbage( "count" ) method?
Is it a bug in my code or in Corona's SDK?

The memory leak in this sample is negligible, but the code here is the base for my state machine where the memory leak becomes noticible.

Appriciate any help / info on this issue,
Thanks,
EZ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
-- vars local
local main_sprt         = nil
local img_sprt          = nil
local big_btn           = nil
 
-- forward declerations
local tapCb
 
 
 
----------------------------------------------------------------------------------------------------
-- init
----------------------------------------------------------------------------------------------------
local function init()
        
        -- main_sprt
        main_sprt = display.newGroup()
        
        -- big_btn
        big_btn = display.newRect( 0, 0, 128, 128 )
        big_btn:setFillColor( 0, 0, 255 )
        big_btn.x = 0.5 * display.contentWidth
        big_btn.y = display.contentHeight - big_btn.height
        big_btn:addEventListener( "tap", tapCb )
        
end
 
----------------------------------------------------------------------------------------------------
-- tapCb
----------------------------------------------------------------------------------------------------
function tapCb( evt )
        
        -- remove img
        if ( img_sprt ~= nil ) then
                --img_sprt:removeSelf()
                main_sprt:remove( img_sprt )
                img_sprt = nil
        end
        
        -- insert img
        img_sprt = display.newImage( "Default.png" )
        img_sprt.x = 0.5 * display.contentWidth + math.floor( -50 + 100 * math.random() )
        --img_sprt.xScale = 0.25
        --img_sprt.yScale = 0.25
        main_sprt:insert( img_sprt )
        
        -- collecg garbage
        collectgarbage( "collect" )
        
        -- print memory usage
        local memUsage_str = string.format( "memUsage = %.3f KB", collectgarbage( "count" ) )
        print( memUsage_str )
        
end
 
 
 
--##################################################################################################
-- START
--##################################################################################################
init()

Replies

jmp909
User offline. Last seen 4 years 5 weeks ago. Offline
Joined: 14 May 2010

try wrapping it in

if(evt.phase=="ended")

does that make any difference? I'm just wondering if the event keeps any references to objects throughout the phases

i know there's an ansca example that does memory tests of adding/removing images that is meant to work ok

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

No, it doesn't make a difference (I've replaced the "tap" event with a "touch" event)...

But it might have something to do with the event, since the following piece of code doesn't suffer from memory leak although the basic logic is the same (remove and add the same image over and over again):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
local main_sprt = display.newGroup()
local img_sprt = nil
 
for i=1, 10 do
        
        print( "---> " .. i )
        print( "main_sprt.numChildren = " .. main_sprt.numChildren )
        
        -- remove img
        if ( img_sprt ~= nil ) then
                main_sprt:remove( img_sprt )
                img_sprt = nil
        end
        
        print( "main_sprt.numChildren = " .. main_sprt.numChildren )
        
        -- insert img
        img_sprt = display.newImage( "Default.png" )
        img_sprt.x = 0.5 * display.contentWidth + math.floor( -50 + 100 * math.random() )
        img_sprt.y = 0.5 * display.contentWidth + math.floor( -50 + 100 * math.random() )
        img_sprt.alpha = 0.5
        main_sprt:insert( img_sprt )
        
        print( "main_sprt.numChildren = " .. main_sprt.numChildren )
        
        -- collecg garbage
        collectgarbage( "collect" )
        
        -- print memory usage
        local memUsage_str = string.format( "memUsage = %.3f KB", collectgarbage( "count" ) )
        print( memUsage_str )
        local texMemUsage_str = string.format( "texMemUsage = %.3f KB", system.getInfo( "textureMemoryUsed" ) )
        print( texMemUsage_str )
        
end

So I still wonder what can cause this memory leak and how I can prevent it from happening...
Any more ideas?

Tim
User offline. Last seen 9 years 26 weeks ago. Offline
Alumni
Joined: 12 Aug 2010

I'm not seeing a memory leak in the latest build. The terminal output looks like:

memUsage = 67.074 KB
memUsage = 67.152 KB
memUsage = 67.152 KB
memUsage = 67.152 KB
memUsage = 67.152 KB
memUsage = 67.152 KB
memUsage = 67.152 KB

...and so forth regardless of how many images I create/destroy. Which build are you using? I'm using a different image for Default.png, obviously, but I don't know why/if that would matter.

Tim

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Tim,

My Mac is not with me right now, so I can't tell you which build I'm using, only that I've downloaded the SDK about 2 months ago.

Is that the output of the first sample of code (with the tap event)?
Cause the second sample of code doesn't show any memory leak for me, too.

If you don't see any memory leak with the first sample, that's good news.
In that case I'll download the latest build and test it :)

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Tim,

Bad news...

I've installed the latest SDK build: Version 2010.243 (2010.12.2)
The previous SDK build I was using was: Version 2.0.0 (2010.9.16.148)

Same results:
--------------------------------------------------
Copyright (C) 2009-2010 A n s c a , I n c .
Version: 2.0.0
Build: 2010.243

memUsage = 67.068 KB
memUsage = 67.436 KB
memUsage = 67.623 KB
memUsage = 67.764 KB
.
.
.
memUsage = 69.920 KB
memUsage = 70.061 KB
memUsage = 70.201 KB
--------------------------------------------------

I'm using the Default.png image taken from the StreamingVideo sample (some Corona text and images on a white background), but as you said I don't think it matters.
I can send you the zipped project if it helps.

I've tested it on my iPhone 3G as well (I've added a text field to output the memory usage )- same results (different numbers)

I'm using a Mac mini ( 2 GHz inter Core 2 Duo, 1 GB 1067 MHz DDR3 ), Mac OS X Version 10.6.5 to build

As I said, one of the strange things is that if I scale down the image to 0.25, it doesn't leak any more (lines 48-49)...

The reason it bugs me so much is that I've completed my first Corona game which is based on a state-machine I've created.
This state-machine has a similar mechanism like the described code (add graphic objects, remove them, add another etc.).
My game is leaking (with every state change) and I suspect it is for the same reasons...

On the same subject - is there a way or a tool to do memory profiling with Corona projects?

Here is, again, the code which causes the leak (with an added text filed to test it on devices):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
-- vars local
local main_sprt         = nil
local img_sprt          = nil
local big_btn           = nil
local mem_txt            = nil
 
-- forward declerations
local tapCb
 
 
 
----------------------------------------------------------------------------------------------------
-- init
----------------------------------------------------------------------------------------------------
local function init()
        
        -- main_sprt
        main_sprt = display.newGroup()
        
        -- big_btn
        big_btn = display.newRect( 0, 0, 128, 128 )
        big_btn:setFillColor( 0, 0, 255 )
        big_btn.x = 0.5 * display.contentWidth
        big_btn.y = display.contentHeight - big_btn.height
        big_btn:addEventListener( "tap", tapCb )
 
        -- mem_txt
        mem_txt = display.newText( 0, 0.5 * display.contentWidth, display.contentHeight - 32, native.systemFont, 12 )
        mem_txt:setTextColor( 128, 128, 128 )
                
end
 
----------------------------------------------------------------------------------------------------
-- tapCb
----------------------------------------------------------------------------------------------------
function tapCb( evt )
        
        -- remove img
        if ( img_sprt ~= nil ) then
                --img_sprt:removeSelf()
                main_sprt:remove( img_sprt )
                img_sprt = nil
        end
        
        -- insert img
        img_sprt = display.newImage( "Default.png" )
        img_sprt.x = 0.5 * display.contentWidth + math.floor( -50 + 100 * math.random() )
        --img_sprt.xScale = 0.25
        --img_sprt.yScale = 0.25
        main_sprt:insert( img_sprt )
        
        -- collecg garbage
        collectgarbage( "collect" )
        
        -- print memory usage
        local memUsage_str = string.format( "memUsage = %.3f KB", collectgarbage( "count" ) )
        mem_txt.text = memUsage_str
        print( memUsage_str )
        
end
 
 
 
--##################################################################################################
-- START
--##################################################################################################
init()

Magenda
User offline. Last seen 4 years 2 weeks ago. Offline
Joined: 2 Jul 2010

Not sure about this, but aren't you autodeleting the local variables you define, by setting them to nil? I suspect that whatever reference to them later in your code just creates new global variables.

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Magenda,

Are you refereeing to the img_sprt I'm setting to nil?
As far as I understand, this is exactly what tells the system to free the memory...

Did you try this code on your machine?
Did you get a memory leak?

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Any news here?
Was anyone able to reproduce this memory leak?

Appreciate any help with this issue...

Tim
User offline. Last seen 9 years 26 weeks ago. Offline
Alumni
Joined: 12 Aug 2010

Weird, I thought I sent a reply...anyway, yes I was able to reproduce the issue with the Default.png you were using, and I filed a bug for engineering to take a look.

Perhaps this is cold comfort, but the leak is limited to the Lua-part of the Corona runtime; the texture memory usage (on the C++ side) remains constant throughout, which you can monitor with system.getInfo( "textureMemoryUsed"), e.g.:

1
 local memUsage_str = string.format( "memUsage = %.3f KB.  texture = %.3f", collectgarbage( "count" ), system.getInfo( "textureMemoryUsed") )

If I hear any updates on this issue that will help, I'll let you know.

Tim

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Thanks Tim,

Yes, I've noticed that texture memory stays the same.

Is this bug thread available to us developers? Can you add a link to it?

Magenda
User offline. Last seen 4 years 2 weeks ago. Offline
Joined: 2 Jul 2010

@ez123

Using your code "as is" in post #5 (within an dummy scene template I have for testing things) and with the newest Corona build, there is no leak here. Stable memory after continuous clicks... (I have used a different image though)

memUsage = 181.282 KB
memUsage = 181.142 KB
memUsage = 181.142 KB
memUsage = 181.196 KB
memUsage = 181.196 KB
memUsage = 181.196 KB
memUsage = 181.196 KB
memUsage = 181.196 KB
memUsage = 181.196 KB

...

memUsage = 181.196 KB
memUsage = 181.196 KB
memUsage = 181.196 KB

EDITED

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Thanks Magenda, for testing it :)

Yes, it seems to have different results for different images (see Tim's posts).

If you are not tired of trying, try to use the image I've mentioned (from Corona's SDK sample) and see if you still don't get memory leak.

Magenda
User offline. Last seen 4 years 2 weeks ago. Offline
Joined: 2 Jul 2010

With the Default.png from Streaming Video sample I get:

memUsage = 181.205 KB
memUsage = 181.338 KB
memUsage = 181.525 KB
memUsage = 181.666 KB
memUsage = 181.807 KB
memUsage = 181.947 KB
memUsage = 182.088 KB
memUsage = 182.229 KB
memUsage = 182.369 KB
memUsage = 182.510 KB
memUsage = 182.650 KB
memUsage = 182.791 KB
memUsage = 182.932 KB
memUsage = 183.072 KB
memUsage = 183.213 KB
memUsage = 183.354 KB
memUsage = 183.869 KB
memUsage = 184.010 KB

Heh... try however to scale the image down after creating it: img_sprt:scale(0.1,0.1)
You again get no leak :)

memUsage = 181.307 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB
memUsage = 181.244 KB

Weird!

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Yeap, weird indeed...

mykyl66
User offline. Last seen 8 years 29 weeks ago. Offline
Joined: 12 Oct 2010

This is something I just noticed myself. after a few days trying to find where the leak was happening I have decided that somehow not all the memory is being released no matter what i do. I am about to try your scale the object trick and see if that makes a difference.

Cheers

Mike R

thegwill
User offline. Last seen 6 years 48 weeks ago. Offline
Joined: 21 Aug 2010

Is it particular image format that cause problems? all PNGs or just some?

mykyl66
User offline. Last seen 8 years 29 weeks ago. Offline
Joined: 12 Oct 2010

Any more news on this issue? Any workarounds? It was mentioned to me to save my images as png-24 but that's not made any difference to me.

I am noticing an increase of 3 or 4kb each time I reload a level and this is after checking and double checking and well you get the picture.

Maybe I am being too much of a perfectionist but I hate anything that I have no idea why it is not doing what I expect. :D

Maybe whats being suggested here is that i shrink all the images before removing them??? ;)

Cheers

Mike R

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Waiting for an update on this issue as well.
My state machine, which builds and destroys screens, leaks really bad because of this bug...

@mykyl66
Did you try it on the newest build?

EZ

mykyl66
User offline. Last seen 8 years 29 weeks ago. Offline
Joined: 12 Oct 2010

Yes I am working with the latest build.

Cheers

Mike R

jonbeebe
User offline. Last seen 6 years 44 weeks ago. Offline
Joined: 26 Jul 2010

I'm also experiencing this. I'm using the latest daily build (as of morning of March 7) and I notice that everytime I change a scene, print( garbagecollect("count") ) continues to increment. With MANY different "scenes" in my app, this eventually climbs to an unbearable amount of memory being used up.

Texture memory is stable, however.

Any updates on this issue? Also... to re-state a question mentioned a couple posts before me, does the scaling-down of the object before removal really help?

jonbeebe
User offline. Last seen 6 years 44 weeks ago. Offline
Joined: 26 Jul 2010

I tried the scaling trick in my project to no avail.

With some of my heavier scenes, I am seeing a HEAVY increase when printing the output of collectgarbage("count") so this is going to cause major probs for me if it's not addressed.

My texture memory looks great. Everything seems to work; however, the actual memory usage based on Lua's output just climbs and climbs and climbs.

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

@ jonbeebe

I've mentioned the scaling-down just as a strange angle to this issue (which might help the Ansca staff to locate and fix that bug).
I don't think it should serve as a workaround (even if it works, and as you mentioned it doesn't).

I wasn't able to solve or to find any workaround since.
I agree with you that this is a major issue, preventing us from developing a game with many heavy scenes.
Personally, this is really frustrating, since my current game is a nice platform game, with many scenes.

As you can see (post #9), Tim from the Ansca staff has filed a bug on this issue a few months ago.
I hope that now (with your post added to this thread), the Ansca staff will be able to update us on this issue...

Tim
User offline. Last seen 9 years 26 weeks ago. Offline
Alumni
Joined: 12 Aug 2010

I wasn't able to reproduce the original bug (from the code sample provided above) in build 302 or later. What builds are people using? Can someone provide another test case that repros the issue again?

Thanks
Tim

jonbeebe
User offline. Last seen 6 years 44 weeks ago. Offline
Joined: 26 Jul 2010

@ez123: Can you retest your code in build 312 or something past 307 (as Tim describes) to confirm if the "bug" is still present or not?

-Thanks!

Tom
User offline. Last seen 4 years 6 weeks ago. Offline
Joined: 13 Jul 2010

I just ran the code in build #311 and the memory usage doesn't change. When I run it in build 243 or 268 (the last released build) the memory increase with every tap.

I suspect some other memory-related bugs were fixed that also fixed this problem.

-Tom

jonbeebe
User offline. Last seen 6 years 44 weeks ago. Offline
Joined: 26 Jul 2010

@Tom: That's great to hear! Sounds like everything's been resolved in one of the later builds :-)

Tom
User offline. Last seen 4 years 6 weeks ago. Offline
Joined: 13 Jul 2010

I did some testing this morning and figured out why scaling the image (or using a different image) doesn't cause the memory leak. The reason (or bug) is when the blue touch rectangle overlaps the background image (default.png). Touching the blue object where it overlaps the background image causes the small memory leak. I scaled the Default.png image to 50% and moved it up so it wasn't under the blue object and there was no leak. When I drop it down so half of the image was under the blue object, the memory leak only occurred when touching the area where the two objects overlap. It looks like the touch event is also being sent to the background image object even though it doesn't have a listener. This may be related to object being removed and created within the touch listener. Not really sure.

Build #268 (last released build) shows the memory leak.
Daily build #277 crashes simulator when touching the overlapped area.
Daily build #311 shows no memory leak when touching the overlapped area.

In looking at the build history there were a few fixes for a group bug and memory leak associated with Physics addBody which may be related. The bottom line is the problem is fixed in the latest daily builds and will be available to everyone in the next formal release.

jonbeebe
User offline. Last seen 6 years 44 weeks ago. Offline
Joined: 26 Jul 2010

Wow, great work Tom! It's great to hear that the bug is "officially" squashed though :-)

In the next iteration of my cleangroup.lua module, I'll omit the scaling code.

ez123
User offline. Last seen 8 years 13 weeks ago. Offline
Joined: 28 Sep 2010

Great to hear that guys :)
Good to know that one of the most disturbing bugs was resolved.

Viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.