Memory usage in Script performance tab

I have tons of functions on the client that create a lot of objects, such as CreateBulletEffect, CreateBulletDecal, CreateBloodSplatter, etc.

But I made sure they’re all removed properly, so I’m running out of options here

Disable/Enable them in groups, make the groups smaller and smaller until you find the problem(s)

Thing is pretty much every script in the game is reliant on the others, theres only a few that are standalone

@einsteinK
@EchoReaper

Initial research has found that this is a possible root of the problem

local nodes = workspace.Map.Nodes:GetChildren()
local visNodeList = {}


function VisNodes()
	visNodeList = {}
	for _, node in pairs(nodes) do
		if npcLib.LineOfSight(char.Head, node, 512, ignore) then --basically checks if ray between "char.Head" and "node" hits
			visNodeList[#visNodeList + 1] = node
		end
	end
end



while wait(2) do
	VisNodes()
end

The code is used to spawn NPCs on random nodes that are not visible to the player

The #nodes and the source of LineOfSight?

Amount of nodes is around 200-250

function eng.LineOfSight(a, b, dist, ignore)
	local pos1 = a
	local isVector = pcall(function() 
		local x = a.x
	end)
	if not isVector then
		pos1 = a.Position
	end
	local pos2 = b.Position
	local ray = Ray.new(pos1,(pos2-pos1).unit * dist)
	local hit, pos = workspace:FindPartOnRayWithIgnoreList(ray, ignore)
	if hit == b then
		return true
	end
	return false
end

I doubt that is the problem. It clears the visNodeList table every time the function is called meaning there’s no infinite buildup of data. It only runs once every two seconds, and creating a table with a maximum of 200 entries shouldn’t be depleting you of memory.

Well atleast the memory stops running out when I comment it out, need to do further testing though

You should probably do this:

function eng.LineOfSight(a, b, dist, ignore)
	local pos1 = tostring(a):match(",") and a or a.Position
	local pos2 = b.Position
	local ray = Ray.new(pos1,(pos2-pos1).unit * dist)
	return workspace:FindPartOnRayWithIgnoreList(ray, ignore) == b
end

Not using a pcall could help, as calling functions is expensive, certainly with pcall.
You should just make sure it’s always a part/Vector3, and edit the code to act that way.
I’m not too happy with the raycasting, but oh well, can’t do much about that.

You can, instead of doing them all every 2s, just do them the whole time, but do wait() between all nodes.
That should be enough time to collect garbage enough.

You would basicly have:

local nodes = {}
for k,v in pairs(workspace.Map.Nodes:GetChildren()) do
	nodes[v] = false
end

local function visNodes()
	for k,v in pairs(nodes) do
		nodes[k] = npcLib.LineOfSight(char.Head,node,512,ignore)
	end
end

After that, you can just see if a node’s visible by doing nodes[node].
You can even pick some nodes easily:

local function getNodes()
	local res = {}
	for k,v in pairs(nodes) do
		if v then
			table.insert(res,v)
		end
	end
	return res
end

Dat 200x raycasting though

Try creating 200 rays in the command bar and finding what they intersect without any delay – it’s instantaneous and doesn’t kill your memory.

Clearing a table and refilling it the same tick actually uses double the memory.
It takes a moment to collect the garbage.
He was also doing pcall every call, and it would error…

Yeah…

@einsteinK


local nodes = {}
for i=1,1000 do
	local node = Instance.new("Part", workspace)
	node.Anchored = true
	node.CanCollide = false
	node.CFrame = CFrame.new(Vector3.new(math.random(-100,100),1,math.random(-100,100)))
	nodes[i] = node
end


wait(3)
print("Ready?")


local visNodeList = {}


function LineOfSight(node)
	local pos1
	local isVector = pcall(function() 
		error()
	end)
	if not isVector then
		pos1 = workspace.CurrentCamera.CoordinateFrame.p
	end
	local pos2 = node.Position
	local ray = Ray.new(pos1,(pos2-pos1).unit * 999)
	local hit, pos = workspace:FindPartOnRay(ray)
	if hit == node then
		return true
	end
	return false
end


function VisNodes()
	visNodeList = {}
	for _, node in pairs(nodes) do
		if LineOfSight(node) then --basically checks if ray between "char.Head" and "node" hits
			visNodeList[#visNodeList + 1] = node
		end
	end
end






while wait(2) do
	VisNodes()
end

I didn’t get a memory error even with 1,000 nodes – I doubt the issue is with that bit Stealth posted.

It certainly helps hurting, though

So it’s no longer giving the “not enough memory” error?

@einsteinK
@EchoReaper

Alright this issue just went on a whole new level.

It can’t be my scripts anymore since when I try to create a test server with 2 players the player 2 will run out of memory before even loading into the game, so before any of my scripts run.

Could this possibly be a plugin?
^ Is not plugin, I disabled them all and still getting this, though not as easily

How much RAM does roblox use when this happens?
Does studio actually use your GPU?

@einsteinK Around 170mb of memory in the windows task manager

Which surprises me since 32-bit applications can use up to 2 gb of memory on a 64-bit OS iirc

2^32 / 1024 / 1024 / 1024 = 4GB
But yeah, 170MB seems almost nothing.
Maybe with the ignore list it does something with them that suddenly requires a big memory spike?

The ignore table is only declared once per respawn at the top of the ClientMain localscript

local ignore = {char, workspace.Map.NPCs, workspace.Map.Nodes, workspace.Map.Lights, workspace.Map.Sounds, workspace.Map.Spawns, workspace.Decals}