Finding causes for memory leaks in my code

Hey there!

I recently put my game out for beta testing and servers experienced extreme lag and memory leaks.

Refer to this post for more information: Finding Causes For Lag?

I am on a mission now to fix this game breaking issue.

I am looking for how to improve the way my code runs so there isn’t super lag other issues.

I will be updating this topic some, because I can’t add all the code at once.

To start off I have my Main Server Control script, this is where players get all their data and everything they need to play the game.

function onPlayerEntered(player)
	
	--Create a key to store player stats
-- the first part is just getting data
	local cheeseKey = "user_" .. player.userId .. "_cheese"
	local statsKey = "user_" .. player.userId .. "_Stats"
	if(datastore:GetAsync(cheeseKey) == nil) then
		datastore:SetAsync(cheeseKey, true)
		datastore:SetAsync(statsKey, {0, 500, 1, "DefaultTrail", "DefaultAnim", "DefaultPet", 0, 1, 0, 0, 
			"DefaultParticleTrail", {}, 0, "Park", {}, {}, 0, 0})
		-- Fetch badge information
		local success, badgeInfo = pcall(function()
			return BadgeService:GetBadgeInfoAsync(badgeID)
		end)
		if success then
			-- Confirm that badge can be awarded
			if badgeInfo.IsEnabled then
				-- Award badge
				local awarded, errorMessage = pcall(function()
					BadgeService:AwardBadge(player.UserId, badgeID)
				end)
				if not awarded then
					warn("Error while awarding badge:", errorMessage)
				end
			end
		else
			warn("Error while fetching badge info!")
		end
		
		
		
	end
	--game.ReplicatedStorage.BadgePlayedEvent:Fire(player)
	print(player)
	--Load in player's last saved stats
	--local init = datastore:GetAsync(initKey)
	local dataStats = nil
	local success, err = pcall(function()
		dataStats = datastore:GetAsync(statsKey)
	end)
	if success then
		print("Successfully Got " .. player.Name .. "'s Data!")
	else
		repeat 
		      warn("Retrying, count:", "\nError:", err)
		      wait(7)

					success, err = pcall(function()
					dataStats = datastore:GetAsync(statsKey)
				end)
		until success
	end
	if dataStats[18] == nil then
		table.insert(dataStats, 0)
	end
	local steps = dataStats[1]
	local points = dataStats[2]
	local speed = dataStats[3]
	local trail = dataStats[4]
	local anim = dataStats[5]
	local pet = dataStats[6]
	local xp = dataStats[7]
	local level = dataStats[8]
	local orbsBadge = dataStats[9]
	local winsBadge = dataStats[10]
	local particle = dataStats[11]
	local bought = dataStats[12]
	local rebirth = dataStats[13]
	local place = dataStats[14]
	local PUA = dataStats[15]
	local PUT = dataStats[16]
	local snack = dataStats[17]
	local moneyBadge = dataStats[18]
	print(dataStats)
	_G.boughtArray[player.userId] = bought
	_G.petUpgradeAmount[player.userId] = PUA
	_G.petUpgradeTime[player.userId] = PUT
	--Creates leaderboard
	
	for key, value in pairs(PetUpgradeTable) do
		if not _G.petUpgradeAmount[player.userId][key] then
			_G.petUpgradeAmount[player.userId][key] = value
		end	
	end
	for key, value in pairs(PetUpgradeTable) do
		if not _G.petUpgradeTime[player.userId][key] then
			_G.petUpgradeTime[player.userId][key] = value
		end	
	end
	
	local petKeyUpdate = "DefaultPet"
	local animKeyUpdate = "DefaultAnim"
	local PtrailKeyUpdate = "DefaultParticleTrail"
	local trailKeyUpdate = "DefaultTrail"
	if _G.boughtArray[player.userId][petKeyUpdate] == nil then
		_G.boughtArray[player.userId][petKeyUpdate] = petKeyUpdate
	end
	if _G.boughtArray[player.userId][animKeyUpdate] == nil then
		_G.boughtArray[player.userId][animKeyUpdate] = animKeyUpdate
	end
	if _G.boughtArray[player.userId][PtrailKeyUpdate] == nil then
		_G.boughtArray[player.userId][PtrailKeyUpdate] = PtrailKeyUpdate
	end
	if _G.boughtArray[player.userId][trailKeyUpdate] == nil then
		_G.boughtArray[player.userId][trailKeyUpdate] = trailKeyUpdate
	end
	--then it will assign it
-- then I have forty plus of these values
   local stepsBoard = Instance.new("IntValue")
	stepsBoard.Name = "Steps"
	stepsBoard.Value = steps
	stepsBoard.Parent = player
-- and then the last part
local serverStorage = game:GetService("ServerStorage")
	local mainLoopInstance = serverStorage.MainLoop:Clone()
	mainLoopInstance.Name = "MainLoop" .. player.UserId
	mainLoopInstance.Disabled = false
	mainLoopInstance.Parent = game:GetService("ServerScriptService")
	
	print(_G.petUpgradeAmount[player.userId])
	print(_G.petUpgradeTime[player.userId])
	-- Connects to newCharacter function
	player.CharacterAdded:Connect(newCharacter)

end

game.Players.PlayerAdded:Connect(onPlayerEntered)

then I have a player leaving function

function onPlayerLeaving(player)
	
	if player.PlayerIsRacing.Value == true then
		game.ReplicatedStorage.GameEndEvent:Fire(player)
	end
	local userId = player.UserId
	
	local steps = player.Steps.Value
	local points = player.Points.Value
	local speed = player.Speed.Value
	local trail = player.PlayerTrail.Value
	local anim = player.PlayerAnim.Value
	local pet = player.PlayerPet.Value
	local xp = player.XP.Value
	local level = player.Level.Value
	local orbsBadge = player.OrbsBadgeCount.Value
	local winsBadge = player.WinsBadgeCount.Value
	local particle = player.PlayerParticleTrail.Value
	local bought = _G.boughtArray[player.userId]
	local rebirth = player.Rebirths.Value
	local place = player.PlayerPlace.Value
	local PUA = _G.petUpgradeAmount[player.userId]
	local PUT = _G.petUpgradeTime[player.userId]
	local snack = player.SwiftSnacks.Value
	local moneyBadge = player.MoneyBadgeCount.Value
	
	local statsKey = "user_" .. player.userId .. "_Stats"
	
	local success, err = pcall(function()
		datastore:SetAsync(statsKey, {steps, points, speed, trail, anim, pet, xp, level, orbsBadge, winsBadge, 
			particle, bought, rebirth, place, PUA, PUT, snack, moneyBadge})
	end)
	if success then
		print("Successfully Saved " .. player.Name .. "'s Data!")
	else
		repeat 
		      warn("Retrying, count:", "\nError:", err)
		      wait(7)
					success, err = pcall(function()
					datastore:SetAsync(statsKey, {steps, points, speed, trail, anim, pet, xp, level, orbsBadge, winsBadge, 
						particle, bought, rebirth, place, PUA, PUT, snack, moneyBadge})
				end)
		until success
	end
	
end

game.Players.PlayerRemoving:Connect(onPlayerLeaving)

This is the first part, there are other things.
What do you see that potentially cause lag or memory leaks?
And yes I know it looks a little messy, and somethings need to be put in tables.

If it helps, I know that when there are only a few people in the server it is just fine, but after a while with a lot of players it gets super laggy, so I wanted to show you the join-leave player script first to see if that was the issue.

Thank you!

1 Like

you could replace this with a for loop

wouldn’t help with your lag problem too much but it would stop more repeated code

2 Likes

Ok, thanks I will look into that!

The next possible reason for extreme lag, when players join everyone gets a pet and these pets are each constantly running this code

local TweenService = game:GetService("TweenService")
local Object = script.Parent
local NAME = Object.NameValue
wait(3)
local character = NAME.Value
local player = game.Players:GetPlayerFromCharacter(character)
if NAME.Value ~= nil then
	script.Parent.Head.AlignOrientation.Attachment1 = character:WaitForChild("Head").NeckRigAttachment
else
	Object:Destroy()
end

function newCharacter(character)

	Object:Destroy()
end
player.CharacterAdded:Connect(newCharacter)

function onPlayerLeaving(player)

	if player.Name == character.Name then
		Object:Destroy()
	end
end

game.Players.PlayerRemoving:Connect(onPlayerLeaving)

while true do
	wait()
	if character.Humanoid.Health > 0 then
		local tweenInfo = TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, 0, false, 0)
	 	
		local tween = TweenService:Create(Object.Head, tweenInfo, {CFrame = character.Head.NeckRigAttachment.CFrame:ToWorldSpace(character.Head.CFrame * CFrame.new(2, 1, 1))} )
	 
		tween:Play()
	else
		Object:Destroy()
	end	
end

Is the while loop an issue?

you could replace the loop with a HealthChanged event

this way it only runs if it needs to run

The health is just a check to make sure the player is still alive, the pet needs to be constantly tweening behind the player’s shoulder

oh yea my bad
does the tweening effect when you don’t move?

you could run it when the position property changes

function Test()

end

HumanoidRootPart:GetPropertyChangedSignal("Position"):Connect(Test)

idk if this would work for you or not

1 Like

I am also using wait() a lot in my code, is that potentially bad?