Garbage Collector and FFI

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Imnotaplayer
Prole
Posts: 2
Joined: Thu Dec 15, 2022 6:31 pm

Re: Garbage Collector and FFI

Post by Imnotaplayer »

UnixRoot wrote: Thu Jun 13, 2024 8:19 am Sorry for the late reply, but this time I have an example that crashes because of the garbage collector. You don't have to do anything. Just start the program, wait for the garbage to raise until around 1024 kb, then the garbage collector kicks in and kills everything.

If you disable the the line wich counts and displays the garbage, the program lives a little longer. If you disable the garbage collector completely, it lives forever. I had it run over night without any crashes.

Code: Select all

local data = {
  -- ...
}

local ptr = {
 -- uses data
}

local terrainTex = {
  -- ...
}

local terrainHeight ={
  -- ...
}

local terrainPtr = {
  -- uses terrainTex
}

local terrainHeightPtr = {
  -- uses terrainHeight
}

-- data, terrainTex and terrainHeight are never referenced again, therefore will be garbage collected.
The first solution I can think of is creating a global reference table.

Code: Select all

_G.GCRef = {} -- not a local variable, otherwise it would also get collected (unless you reference it elsewhere)
_G.GCRef.data = data
_G.GCRef.terrainTex = terrainTex
_G.GCRef.terrainHeight = terrainHeight
This fixes the problem.

:getFFIPointer() returns a reference to where an object is, not a reference to the object. So unless you use that object later, the objects you call :getFFIPointer() on can be garbage collected and the pointer it gave is invalidated.

Code: Select all

-- in love.run
data = data
terrainTex = terrainTex
terrainHeight = terrainHeight
Even this is sufficient to prevent the collection of these tables.
User avatar
pgimeno
Party member
Posts: 3673
Joined: Sun Oct 18, 2015 2:58 pm

Re: Garbage Collector and FFI

Post by pgimeno »

To make it crash (or not) immediately, it suffices to add a `collectgarbage("collect")` to the beginning of e.g. love.update(). You don't have to wait at all; at least in my system.

I've added debug code to see which objects are garbage-collected:

Code: Select all

do
  local mt
  local function gc(x) print(x) end
  mt = debug.getmetatable(terrainTex[1])
  mt.__gc = gc
  mt = debug.getmetatable(terrainHeight[1])
  mt.__gc = gc
  mt = debug.getmetatable(data.depthLUT)
  mt.__gc = gc
end
-- _G.pin = {terrainTex, terrainHeight, data.yBuffer, data.depthLUT}
The above code proves that these objects are garbage-collected. Pinning them through a global, as Imnotaplayer suggested, which can also be done with something like the commented line in the above snippet, fixes it for me too.
RNavega
Party member
Posts: 385
Joined: Sun Aug 16, 2020 1:28 pm

Re: Garbage Collector and FFI

Post by RNavega »

From what the OP was saying, on their end, variables whether local or global weren't being enough to survive the FFI objects (as if they were acting like weak references), and that the only way to fix it was to put those objects in a Lua table (either with a key or index):
UnixRoot wrote: Fri May 17, 2024 10:46 am
RNavega wrote: Fri May 17, 2024 10:28 am Since you already seem to be keeping references to the things being used (at least the obvious ones), I'd think that the problem might be happening from something not obvious.
Of course, I tried that too, storing the pointer in an extra variable. It still gets garbage collected. The only thing that prevents it from being garbage collected instantly after program start, is to pack everything into LUA tables.
User avatar
pgimeno
Party member
Posts: 3673
Joined: Sun Oct 18, 2015 2:58 pm

Re: Garbage Collector and FFI

Post by pgimeno »

RNavega wrote: Sat Jun 15, 2024 12:38 am From what the OP was saying, on their end, variables whether local or global weren't being enough to survive the FFI objects (as if they were acting like weak references), and that the only way to fix it was to put those objects in a Lua table (either with a key or index):
UnixRoot wrote: Fri May 17, 2024 10:46 am
RNavega wrote: Fri May 17, 2024 10:28 am Since you already seem to be keeping references to the things being used (at least the obvious ones), I'd think that the problem might be happening from something not obvious.
Of course, I tried that too, storing the pointer in an extra variable. It still gets garbage collected. The only thing that prevents it from being garbage collected instantly after program start, is to pack everything into LUA tables.
Maybe the problem was the focus on the pointers, rather than on the objects being pointed at. I've put in bold what has made me think so.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 2 guests