Is server memory meant to go up and never come down? For servers that are open for a long time
It depends.
If itâs steadily increasing over time, that could indicate thaht you have memory leaks somewhere. I.e. youâre allocating memory and not freeing it again when it should be freed. Hereâs a very simplified example:
local t = {}
while wait() do table.insert(t, 1) end
This will just fill the table with more and more numbers, which obviously require memory to be stored which canât be GCâed, causing a memory leak. Unless this is part of your gameâs logic, in which case itâs not a memory leak, that just means your design doesnât use a constant amount of memory which is normal and fine. E.g. in a building game where players can create parts, obviously memory goes up as more and more parts are created. So you canât just look at a graph of memory usage and determine if thereâs a memory leak or not.
Memory leaks are unfortunately tricky to track down, in part because we donât have direct control over memory in garbage-collected languages like Lua so we canât just go through every single allocation and read the code to verify that thereâs a corresponding freeing of that memory.
If memory usage is out of control and causing performance issues then you definitely need to deal with it, but if itâs just a slow trickle over many hours then it might not be worth the considerable effort it might take to fix it.
Yes, you can always force a shutdown if necessary.
https://developer.roblox.com/en-us/api-reference/function/DataModel/Shutdown
Thanks for replying, if you have a table such as
local HitPlayers = {}
table.insert(HitPlayers,c)
and you donât nil the table will this get auto gcâd?
Short answer, no.
If you keep (strong) references to objects in the table or anywhere else forever, then those objects wonât be GCâed even if you Destroy them. The table itself will be GCâed when all references to it are gone. That happens when you make all references to it refer to something else, or when the refs goes out of scope.
Make a variable refer to something else:
local t = {hitPlayer}
hitPlayer:Destroy() --Won't be GC'ed 'cause hitPlayer refers to the Player object
hitPlayer = nil --Now there's only 1 ref to the Player object, which is in t
t = nil --No variables refer to the table, so t and hitPlayer can be GC'ed
while wait() do end --Prevent the script from ending, which would make t and hitPlayer go out of scope
Make the variable referencing the table go out of scope:
local t = {hitPlayer}
hitPlayer:Destroy() --Won't be GC'ed 'cause hitPlayer refers to the Player object
hitPlayer = nil --Now there's only 1 ref to the Player object, which is in t
--The script ends here, so t goes out of scope, getting GC'ed, removing the ref to `hitPlayer`
Make the variable referencing the table go out of scope (again):
do
local t = {hitPlayer}
hitPlayer:Destroy() --Won't be GC'ed 'cause hitPlayer refers to the Player object
hitPlayer = nil --Now there's only 1 ref to the Player object, which is in t
--The scope ends here, so t goes out of scope, getting GC'ed, removing the ref to `hitPlayer`
end
while wait() do end
Make the table not refer to the object:
local t = {hitPlayer}
hitPlayer:Destroy()
hitPlayer = nil --Now there's only 1 ref to the Player object, which is in t
table.remove(t, table.find(t, hitPlayer)) --t no longer refers to hitPlayer
while wait() do end
If you want to prevent a table from preventing GC, look up weak tables.
I will take a look into weak tables?
local HitPlayers = {}
table.insert(HitPlayers,c)
HitPlayers = nil
So this wonât get gcâd iâd have to remove everything in the table first?
Since there are no references to HitPlayers, it can itself get cleaned up. When that happens, HitPlayers it wonât refer to anything anymore. If it was the last thing that referred to whatever is stored in c
, then that will have no references left to it so it can be cleaned up.
But since youâre not setting c
to nil, that variable will continue to refer to whatever it stores, keeping it in memory forever.
Of course all of this only matters if the lines of code that follow contain an infinite loop to prevent every var in the script to go out of scope, or a reference to the variables HitPlayers
and c
that doesnât get cleaned up, such as an event connection. So if this is the entire script:
local HitPlayers = {}
table.insert(HitPlayers,c)
HitPlayers = nil
then everything gets cleaned up because after HitPlayers = nil
runs the script is done and all the variables go out of scope, removing their references. If instead you have
local HitPlayers = {}
table.insert(HitPlayers,c)
HitPlayers = nil
while wait() do end
then the script will never end. The table that HitPlayers
refers to will be cleaned up because you remove the reference to the table (you make HitPlayers refer to something else). You havenât defined c
in the snippet and all of this is assuming that c
is some value. That value will never be cleaned up because you never set the variable c
to refer to something else.
âcâ Would be refer to a character,
âBut since youâre not setting c
to nil, that variable will continue to refer to whatever it stores, keeping it in memory forever.â
I would need to set c to nil aswell or can I just nil the table for it be cleaned up?
local c = Character
local HitPlayers = {}
table.insert(HitPlayers,c)
HitPlayers = nil
Yes. But thereâs more âpotential for memory leaksâ in tables not being cleaned up. A variable referring to a table can potentially prevent 1000s or even more things from being cleaned up, while a variable referring to a single object that doesnât prevent other objects from being GCâed at most keeps that one object in memory.