How to remove elements from a table and MEMORY?

I have a big problem with the usage of memory in my game. It needs more and more memory. I think it’s because the objects, that I remove from a table, remain in memory. So, I write some little test codes to understand what happens.

1.) Memory usage: low (0.3 Mb), high (63 Mb), low(0.3 Mb) => all right (only works with the call: collectgarbage())

local elements = {} local length = 1000000 timer.performWithDelay( 1500, function() for i = 1, length, 1 do table.insert( elements, { "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum." } ) end end ) timer.performWithDelay( 2500, function() elements = nil collectgarbage() end ) local function printMemUsage() print( "System Memory Used:", string.format( "%.03f", collectgarbage("count") / 1000 ), "Mb" ) end timer.performWithDelay( 1000, function() printMemUsage() end, 0 )

2.) Memory usage: low (0.3 Mb), high(63 Mb), midde (16 Mb), goes higher and higher => not ok

local elements = {} local length = 1000000 timer.performWithDelay( 1500, function() for i = 1, length, 1 do table.insert( elements, { "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum." } ) end end ) timer.performWithDelay( 2500, function() for i = length, 1, -1 do table.remove(elements, i) end collectgarbage() end ) local function printMemUsage() print( "System Memory Used:", string.format( "%.03f", collectgarbage("count") / 1000 ), "Mb" ) end timer.performWithDelay( 1000, function() printMemUsage() end, 0 )

If I set the table to nil, it needs no longer memory. But if I remove all the elements with table.remove() the memory goes crazy. I tested it with elements[i] = nil, but there was the same problem.

I hope someone can explain me what’s wrong. Thanks.

Garbage collection is automatic when the CPU is idle… but if you have a heavy game you won’t actually get any idle time so you must manage resources carefully.  Always remove and nil references out.

My second example is not a heavy game. But it needs more and more memory. How to solve this problem? 

You can easily copy the code into an empty project to see (in console) what I mean. 

In a game I can’t nil the table variable (like in the first example), because I don’t want to kill ALL elements. 

the memory will increase because of creating a new string object every 1,000ms

@Sphere Game Studio: Thank you for your answers.

Now I understand, that the garbage collector doesn’t work automatically in all situations.   

I found a solution: I call the collectgarbage function in an interval. Here is the full example.

local elements = {} local length = 1000000 timer.performWithDelay( 1500, function() for i = 1, length, 1 do table.insert( elements, { "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum." } ) end end ) timer.performWithDelay( 2500, function() for i = length, 1, -1 do table.remove(elements, i) end end ) timer.performWithDelay( 5000, function() collectgarbage() end, 0 ) local function printMemUsage() print( "System Memory Used:", string.format( "%.03f", collectgarbage("count") / 1000 ), "Mb" ) end timer.performWithDelay( 1000, function() printMemUsage() end, 0 )

Garbage collection is automatic when the CPU is idle… but if you have a heavy game you won’t actually get any idle time so you must manage resources carefully.  Always remove and nil references out.

My second example is not a heavy game. But it needs more and more memory. How to solve this problem? 

You can easily copy the code into an empty project to see (in console) what I mean. 

In a game I can’t nil the table variable (like in the first example), because I don’t want to kill ALL elements. 

the memory will increase because of creating a new string object every 1,000ms

@Sphere Game Studio: Thank you for your answers.

Now I understand, that the garbage collector doesn’t work automatically in all situations.   

I found a solution: I call the collectgarbage function in an interval. Here is the full example.

local elements = {} local length = 1000000 timer.performWithDelay( 1500, function() for i = 1, length, 1 do table.insert( elements, { "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum." } ) end end ) timer.performWithDelay( 2500, function() for i = length, 1, -1 do table.remove(elements, i) end end ) timer.performWithDelay( 5000, function() collectgarbage() end, 0 ) local function printMemUsage() print( "System Memory Used:", string.format( "%.03f", collectgarbage("count") / 1000 ), "Mb" ) end timer.performWithDelay( 1000, function() printMemUsage() end, 0 )