Page 4 of 5
Re: Love2d stops running after awhile
Posted: Wed Dec 30, 2020 5:00 pm
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).
Re: Love2d stops running after awhile
Posted: Thu Dec 31, 2020 12:28 am
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.
Re: Love2d stops running after awhile
Posted: Thu Dec 31, 2020 2:16 am
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
?) but for real I'm coming with one soonish...
Re: Love2d stops running after awhile
Posted: Thu Dec 31, 2020 12:03 pm
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
Re: Love2d stops running after awhile
Posted: Thu Dec 31, 2020 1:16 pm
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.
Re: Love2d stops running after awhile
Posted: Thu Dec 31, 2020 2:09 pm
by Gunroar:Cannon()
I opened the last of the sites younposted for me .. and here's the basic rundown:
me: wow
, so many object pooling libraries
me:*opens link one*
me:*opens link two*
me:
(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 (
) 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
.
Re: Love2d stops running after awhile
Posted: Thu Dec 31, 2020 2:11 pm
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)
Re: Love2d stops running after awhile
Posted: Thu Dec 31, 2020 2:45 pm
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?
Re: Love2d stops running after awhile
Posted: Thu Dec 31, 2020 7:03 pm
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.
Re: Love2d stops running after awhile
Posted: Fri Jan 01, 2021 3:31 pm
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:
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.