Garbage Collection - why does it keep increasing?

Hi everyone

I’m new to Corona, I starting making a game and it’s awesome so far!

I started to optimize it (find leaks, etc), but I came to an issue with the garbage collector: even with an empty scene, the total memory keeps increasing. I know you guys say that up to 8Kb is normal and expected behavior, but even with no objects at all?

Here is the full content of the test main.lua file:

function printGC(event) print("total mem used:" .. collectgarbage('count')) end Runtime:addEventListener('enterFrame', printGC)

This prints out increasing numbers: starts at 250 and when it get to ~420, then starts the GC and resets to ~250.

What does Corona do in the back that makes the GC keep increasing all the time? And can this be stopped/prevented? I know you could use 

collectgarbage("stop")

but I’m asking to stop the reason why the memory used is increasing, not the actual process of freeing the memory.

Hi @admin6028,

Welcome to Corona, I’m glad that your initial experience is positive! To clarify, you state that the memory count starts around 250, then increases to ~420, but then drops back down to ~250 and remains around that range? Does it continue to climb above 420, or does it become approximately level/steady?

If the latter, then it’s not concerning… it’s normal for the memory to bump up slightly in the beginning (higher than the absolute starting value). What would be concerning is if the memory continued to climb upwards and upwards, and never reduced back to a fairly steady level… that would indicate a clear memory leak.

Hope this helps,

Brent

Hi Brent!

Thanks very much for your answer!

To answer your question, it does NOT become steady, after dropping to 250 it keeps increasing to ~450 again, then drops again to ~250 and so on and on. This happens in the Corona simulator (Borderless Android 480x800) - but I’m sure the resolution should not matter since everything is just black and nothing else is loaded.

I can also notice that if I move the mouse around (in circles over the empty black simulator), the memory used is increasing faster, so it only takes about 2-3 seconds until the Garbage Collector does its thing (instead of ~30 seconds when I just leave it and wait).

Of course, as you can see, there is no Event Listener for mouse, touch or any other kind of listener. The code above is really everything. In the folder, there is only a config.lua file that looks like this (the standard Ultimate config.lua file):

--calculate the aspect ratio of the device: local aspectRatio = display.pixelHeight / display.pixelWidth application = { content = { width = aspectRatio \> 1.5 and 320 or math.ceil( 480 / aspectRatio ), height = aspectRatio \< 1.5 and 480 or math.ceil( 320 \* aspectRatio ), scale = "letterBox", fps = 30, imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, }, }, }

So it looks like there is still a leak. Am I missing something?

Just to clarify: for testing purposes, I created an empty project: a folder named “test_gc” with only 2 files:

  • main.lua - 4 lines of code (as in the first post)

  • config.lua - “standard” Ultimate config.lua file (as in the previous post)

So even with 4 lines of code, where I only print the memory used, the memory used keeps increasing, then lowers (GC cleans stuff), then again, and again. What could cause the leak?

You’re not actually “collecting garbage” when you call garbagecollect(“count”).  You’re just getting a count of Lua memory that is in use.  Going from 250 to 450 on this scale is growing 200,000 bytes of memory, but when you factor in that a single background image on an iPhone 5 is nearly 3,000,000 bytes of memory, it’s not a whole lot.

Why does it reset?  Well garbage collection runs at various intervals.  It’s not a set time like every 30 seconds, but its based on the amount of memory churn and is unpredictable for the most part.  It’s normal for your app’s lua memory to grow in size then drop suddenly then grow back.  That’s just simply memory being allocated and not being reclaimed until a while later.  Now if it keeps growing and growing and you don’t see any resets then you might have a problem.

Every time your enterFrame listener fires, it’s calling a function.  That function is calling a function (print) and all of these could allocate some temporary memory that won’t be reclaimed until collection happens.  While your app doesn’t have any mouse handlers, when you move your mouse around, the operating system is generating events that get passed to the simulator and the simulator is at least looknig at them again, probably allocating a little bit of memory and freeing it back up, but it won’t show as freed until GC runs.

What you’re seeing sounds normal to me. 

Ok, thanks a lot Rob!

So it seems that it actually IS steady, a few hundred kilos is fine :slight_smile: You’re right, compared to 3MB it’s nothing,

Thank you Brent for all your help as well!

Sorry to add in, but mine keeps increasing by 8 megabytes and never drops after I implemented audios. If I remove all of the audios, it stays stable. So what should the code be?

It sounds like you’re always loading audio and never disposing it.  I think you asked this in another thread.  See my answer there:
 

https://forums.coronalabs.com/topic/56607-audio-causing-memory-to-keep-increasing-in-each-restart/

Hi @admin6028,

Welcome to Corona, I’m glad that your initial experience is positive! To clarify, you state that the memory count starts around 250, then increases to ~420, but then drops back down to ~250 and remains around that range? Does it continue to climb above 420, or does it become approximately level/steady?

If the latter, then it’s not concerning… it’s normal for the memory to bump up slightly in the beginning (higher than the absolute starting value). What would be concerning is if the memory continued to climb upwards and upwards, and never reduced back to a fairly steady level… that would indicate a clear memory leak.

Hope this helps,

Brent

Hi Brent!

Thanks very much for your answer!

To answer your question, it does NOT become steady, after dropping to 250 it keeps increasing to ~450 again, then drops again to ~250 and so on and on. This happens in the Corona simulator (Borderless Android 480x800) - but I’m sure the resolution should not matter since everything is just black and nothing else is loaded.

I can also notice that if I move the mouse around (in circles over the empty black simulator), the memory used is increasing faster, so it only takes about 2-3 seconds until the Garbage Collector does its thing (instead of ~30 seconds when I just leave it and wait).

Of course, as you can see, there is no Event Listener for mouse, touch or any other kind of listener. The code above is really everything. In the folder, there is only a config.lua file that looks like this (the standard Ultimate config.lua file):

--calculate the aspect ratio of the device: local aspectRatio = display.pixelHeight / display.pixelWidth application = { content = { width = aspectRatio \> 1.5 and 320 or math.ceil( 480 / aspectRatio ), height = aspectRatio \< 1.5 and 480 or math.ceil( 320 \* aspectRatio ), scale = "letterBox", fps = 30, imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, }, }, }

So it looks like there is still a leak. Am I missing something?

Just to clarify: for testing purposes, I created an empty project: a folder named “test_gc” with only 2 files:

  • main.lua - 4 lines of code (as in the first post)

  • config.lua - “standard” Ultimate config.lua file (as in the previous post)

So even with 4 lines of code, where I only print the memory used, the memory used keeps increasing, then lowers (GC cleans stuff), then again, and again. What could cause the leak?

You’re not actually “collecting garbage” when you call garbagecollect(“count”).  You’re just getting a count of Lua memory that is in use.  Going from 250 to 450 on this scale is growing 200,000 bytes of memory, but when you factor in that a single background image on an iPhone 5 is nearly 3,000,000 bytes of memory, it’s not a whole lot.

Why does it reset?  Well garbage collection runs at various intervals.  It’s not a set time like every 30 seconds, but its based on the amount of memory churn and is unpredictable for the most part.  It’s normal for your app’s lua memory to grow in size then drop suddenly then grow back.  That’s just simply memory being allocated and not being reclaimed until a while later.  Now if it keeps growing and growing and you don’t see any resets then you might have a problem.

Every time your enterFrame listener fires, it’s calling a function.  That function is calling a function (print) and all of these could allocate some temporary memory that won’t be reclaimed until collection happens.  While your app doesn’t have any mouse handlers, when you move your mouse around, the operating system is generating events that get passed to the simulator and the simulator is at least looknig at them again, probably allocating a little bit of memory and freeing it back up, but it won’t show as freed until GC runs.

What you’re seeing sounds normal to me. 

Ok, thanks a lot Rob!

So it seems that it actually IS steady, a few hundred kilos is fine :slight_smile: You’re right, compared to 3MB it’s nothing,

Thank you Brent for all your help as well!

Sorry to add in, but mine keeps increasing by 8 megabytes and never drops after I implemented audios. If I remove all of the audios, it stays stable. So what should the code be?

It sounds like you’re always loading audio and never disposing it.  I think you asked this in another thread.  See my answer there:
 

https://forums.coronalabs.com/topic/56607-audio-causing-memory-to-keep-increasing-in-each-restart/