Love2d stops running after awhile

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.
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: Love2d stops running after awhile

Post by Gunroar:Cannon() »

slime wrote: Mon Dec 28, 2020 8:26 pm At this point I don't think anyone will be able to guess what your code is doing wrong without being able to see and run it in its entirety. People want to help but ...
At this point I actually pinpointed the problem and that it comes from class.lua. Now I don't really want someone to fix my class anymore but rather to see what I did wrong in the object pooling side so I don't make the mistake again and I can move on using one of the other pooling libs recommended. So if anyone can see the problem (just find it,not fix it). that'd be great. (p.s. you can use the 2 pieces of code to run a program where it creates and destroys puffs).
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: Love2d stops running after awhile

Post by pgimeno »

Gunroar:Cannon() wrote: Wed Dec 30, 2020 5:00 pmSo if anyone can see the problem (just find it,not fix it). that'd be great. (p.s. you can use the 2 pieces of code to run a program where it creates and destroys puffs).
I've tried to do just that, and I gave up. If you can provide one, please do.
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: Love2d stops running after awhile

Post by Gunroar:Cannon() »

pgimeno wrote: Thu Dec 31, 2020 12:28 am I've tried to do just that, and I gave up. If you can provide one, please do.
If you're talking about the simulation then I'll be with one in a jiffy...(jiffy translates to 2 or 3 days, just kidding...or am I :P ?) but for real I'm coming with one soonish...
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: Love2d stops running after awhile

Post by Gunroar:Cannon() »

Thnx for waiting and bearing with me, here's the code, just put the other two in the same directory...

main.lua
(edited)

Code: Select all

--edited
null = function() return 5 end
resizeImage = null
inspect = null
log = null
lume = {
    uuid=null,
    randomchoice = function(t)
        return t[math.random(#t)]
    end,
    wordwrap=null
    }
local kwargs = {
    uuid = 4,
    map = {storeBullet=null,kill=null},
    getSource = null
}
game = kwargs
progress = 0

getUpdateCount = null--not needed

class = require "class"
local Puff = require "puff"

local totalPuffs, currentPuffs = 0,0

local function spawnPuff()
    local p = Puff:new(kwargs)
    p.source = nil
    totalPuffs = totalPuffs+1
    table.insert(puffs, p)
    return p
end

function mass()
    for i = 1,1000 do
        spawnPuff()
    end
end

local function destroyPuff()
    local d = puffs[#puffs]
    if d then
        d:destroy()
        puffs[#puffs] = nil
    end
end

function copy(t)
    local tt = {}
    for x, i in ipairs(t) do
        tt[x] = i
    end
    return tt
end

function love.load()
    puffs = {}
    count = 50
end

function love.draw()
    love.graphics.print("Total puffs spawned: "..totalPuffs,10,100,0,2,2)
    love.graphics.print("Current puffs made: "..currentPuffs,10,150,0,2,2)
    love.graphics.print("Garbage in mb: "..collectgarbage("count")/1024,10,200,0,2,2)
    love.graphics.print("texture memory: "..love.graphics.getStats().texturememory/(1024*1024),10,250,0,2,2)
    love.graphics.print("frame rate: "..love.timer.getFPS(),10,300,0,2,2)
end

function love.update(dt)
    --ppuffs = copy(puffs)
    local del = {}
    for i = 1,#puffs do
        puffs[i]:update(dt,1)
        if puffs[i].dead then
            del[i] = true
        end
    end
    
    for i in pairs(del) do 
        --if puffs[i].dead then
            table.remove(puffs,i)
        --end
    end
    
    count = count+1
    if count>3 then
        for x=1,100 do
            destroyPuff()
        end
        count = 0
    end
    
    currentPuffs = #puffs
end

function love.mousereleased()
    --freezes for me at 6000 if object pool size is 5100
    --4000 if size is 3000
    mass()
end

Last edited by Gunroar:Cannon() on Thu Dec 31, 2020 2:17 pm, edited 2 times in total.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
MrFariator
Party member
Posts: 559
Joined: Wed Oct 05, 2016 11:53 am

Re: Love2d stops running after awhile

Post by MrFariator »

First thing first, you have this piece of code in your puff.lua:

Code: Select all

_LOG_FILE = love.filesystem.newFile("game_log.txt","w")
local function log(_str,file)

    local file = file or _LOG_FILE
    local str = lume.wordwrap(inspect(_str,1),90)
    file:write(str.."\n")
    return true
end
You use this to log stuff that happens in your code, at such a rate that I amassed 15 thousand(!) lines in the resulting log file after running it for a couple of seconds. This is an absurd rate, to put it mildly.

Secondly, in your example code provided, you have the following:

Code: Select all

function love.load()
    puffs = {}
    count = 50
end

function copy(t)
    local tt = {}
    for x, i in ipairs(t) do
        tt[x] = i
    end
    return tt
end

function love.update(dt)
    ppuffs = copy(puffs)
    -- ...
end
Thus, you are copying the contents of "puffs" to "ppuffs" (a new table, that is global, that is used as a temporary variable) every frame, creating a lot of garbage. Not only that, it's not exactly efficient and wasteful, to the point you don't need the copy() method at all here. You should only have the single "puffs" table, update the puffs contained therein, and remove the contained objects as necessary.

There may be other issues as well (the table.remove in the love.update, for example), but those two were what immediately stuck out to me. No clue as to why the code crashes at 6000 puffs with the pool size 5100, did not delve too deeply into how class.lua's pooling works.
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: Love2d stops running after awhile

Post by Gunroar:Cannon() »

I opened the last of the sites younposted for me .. and here's the basic rundown:
me: wow :awesome: , so many object pooling libraries
me:*opens link one*
me:*opens link two*
me:
:brows:

(though I have seen object pool libs and will check them out)
pgimeno wrote: Thu Aug 06, 2020 5:21 pm
...
And about 60% of the time or maybe more, those who post only snippets of code with the part where they think the problem is, are wrong..
I guess I'm 40% or less ( :cool: ) since I didn't just blindly post snippets and followed the advice that MrFariator gave me...
MrFariator wrote: Wed Dec 23, 2020 6:56 pm ... you can disable most of the game's logic code (by commenting them out in love.update or wherever else), and then step-by-step enable behavior and see when the issues crop up again. That should help you along with narrowing down the issue.
So...yeah, but you've still been helpful and that code I posted should run and have the same problem, so that should help :P .
Last edited by Gunroar:Cannon() on Thu Dec 31, 2020 2:24 pm, edited 2 times in total.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: Love2d stops running after awhile

Post by Gunroar:Cannon() »

Oh, MrFariator! Thnx for the replies but I know of the log and don't really use it and only added that copy part for the emulation. Those aren't in the actual use. I might come with a revised version(I think a problem might be from destroy) and the code doesn't crash for you?
Edit: I revised the main.lua to remove copying and it proves it still crashes and it's not from copy. (P.S: it crashes right before one is about to get destroyed)
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: Love2d stops running after awhile

Post by pgimeno »

Just to be clear, does the main.lua you've provided still crash on Android? Is there anything that needs to be done to make it crash, or just wait?
User avatar
Gunroar:Cannon()
Party member
Posts: 1143
Joined: Thu Dec 10, 2020 1:57 am

Re: Love2d stops running after awhile

Post by Gunroar:Cannon() »

Just keep tapping(on the screen, that is) until it passes around 6000 or more...because tapping makes more puffs appear. Oh and yes it still crashes.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: Love2d stops running after awhile

Post by pgimeno »

Thanks for the test case. I've simplified it further, removing puff.lua and Löve from the equation. This test case runs with plain LuaJIT:

Code: Select all

jit.off()
game = {}
null = function() end
love = {timer = {getTime = null}}
local BaseClass = require"class"
local Derived = BaseClass:extend("Derived", 2)
for i = 1, 3 do
  local obj = Derived:new()
  print("Destroying " .. i)
  obj:destroy()
  print("Destroyed")
end
The output is:

Code: Select all

Destroying 1
Destroyed
Destroying 2
Destroyed
Destroying 3
And then it hangs for a while until it says:

Code: Select all

luajit: not enough memory
But interrupting while it's hung, gives a hint:

Code: Select all

Destroying 1
Destroyed
Destroying 2
Destroyed
Destroying 3
^Cluajit: ./class.lua:9: interrupted!
stack traceback:
	./class.lua:9: in function 'destroy'
	main.lua:10: in main chunk
	[C]: at 0x555dee0206c0
Sometimes in line 10 instead of 9. And this is the part that is running:

Code: Select all

local function destroyFunc(self,...)
  --  log(name.." pool at "..self.__id.." is being freed.")
    local notActive = POOLS[self.__class].notActive
    notActive[#notActive+1] = self.__id
    return self._destroy(self,...)
end
Line 10 is the one that adds the id to the notActive table. Printing #notActive there, reveals that it's growing endlessly.

Therefore, yes, you have a leak which manifests itself when you have created and destroyed as many objects as the size of the pool. If you create just one more object, its destruction causes an infinite loop of notActive creation that exhausts the memory.

I haven't tried to follow the logic of your object destruction, therefore I don't know the cause of the infinite loop.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 12 guests