Where to put the "task.wait" for performance

i have a loading system that either creates a huge lag spike when loading or slow iteration depending where i put the wait.

local function Read2(track,data)
	--task.wait()   <-----[[lag spike]]
	for i, value in pairs(data) do
                     --task.wait()    <----[[ slow iteration]]
		if value:GetAttribute("Station") ~= station.Value then continue end
		if tostring(value:GetAttribute("AbsoluteKey")) ~= tostring(track:GetAttribute("AbsoluteKey")) then continue end
		if value:GetAttribute("Owner") ~= player.UserId then continue end
		local NewNote = game.ReplicatedStorage.Sounds:FindFirstChild(value:GetAttribute("Instrument")):Clone()
		local pos = value:GetAttribute("Position")
		local len = value:GetAttribute("Size")
		NewNote.Name = value.Name
		NewNote.Position = pos
		NewNote.Size = len
		NewNote.assets.Velocity.Value = tonumber(value:GetAttribute("Velocity"))
		NewNote.LeftScale.Velocityframe.Size = UDim2.new(math.clamp(NewNote.assets.Velocity.Value/16,0,8),0,NewNote.LeftScale.Velocityframe.Size.Y.Scale,0)
		local notedescription = NewNote.RightScale.NoteDescription
		notedescription.ImageLabel.Velocity.Text = tostring("Velocity: "..NewNote.assets.Velocity.Value)
		NewNote.Parent = track
	end
end

-------------------------------------------------------------------------------------------------------------


game.ReplicatedStorage.Remotes.Read3.OnClientEvent:Connect(function(plr)

	loaded = false
	local data = game.CollectionService:GetTagged(player.UserId)
	if player ~= game.Players.LocalPlayer then return end
	script.Parent.Parent.processing.Visible = true
	for k=1, #tracks do local track = tracks[k]
                --task.waait()    <-------[[ both if not none above otherwise, slow iteration]]
		if not track:IsDescendantOf(script.Parent.canvas) then continue	end
		Read2(track,data)
	end
	loaded = true
	script.Parent.Parent.processing.Visible = false
	game.ReplicatedStorage.Remotes.FinishLoading:FireServer(script.Parent.Parent.station.Value)
end)
5 Likes

Maybe try …

local rs = game:GetService("RunService")  -- on top of script

rs.Stepped:Wait() -- use like task.wait(), it will step with the screen update.

tried that before i tried task.wait

script.Parent.Parent.processing.Visible = false
rs.Stepped:Wait() -- or task.wait(0.33) or (0.033) or (1)
loaded = true
game.ReplicatedStorage.Remotes.FinishLoading:FireServer(script.Parent.Parent.station.Value)

That’s just the one wait for this.
I try not to leave task.wait() ← blank

now im getting lag spikes every few seconds and got this:

Has this ever worked? How many things are you reading with pairs(data)?

make it wait only just before it would start to lag, it would look something like this:

local a = os.clock()
for .... do
    if os.clock() - a >= 1/60 then
        wait()
        a = os.clock()
    end
2 Likes

over 1k image buttons being created frameGui

i never heard of that method, ill try that

im still getting the heavy lag spike

first of all, are you crazy???

over 1k image buttons being created frameGui

if youre still getting lag spikes then it might be because you are calling the Read2 function within another for loop, try putting that fast wait method inside the other for loop too

1 Like

no im not crazy, this explains why players can end up with over 1k gui out of the 10k posible

and i tried that, the lagg spike died down a little bit but its still heavy

local function Read(value)
	if value:GetAttribute("Station") ~= script.Parent.Parent.station.Value then return end
	if value:GetAttribute("Musician_ID") ~= script.Parent.Parent.ID.Value then return end
	local a = os.clock()
	for i, track in pairs(tracks) do
		
		if os.clock() - a >= 1/60 then
			wait()
			a = os.clock()
		end
		if not track:IsDescendantOf(script.Parent.canvas) then continue	end
		if tostring(value:GetAttribute("AbsoluteKey")) ~= tostring(track:GetAttribute("AbsoluteKey")) then continue end
		if value:GetAttribute("Owner") ~= player.Name then continue end
		local NewNote = game.ReplicatedStorage.Sounds:FindFirstChild(value:GetAttribute("Instrument")):Clone()
		NewNote.Name = value.Name
		local NewString = string.gsub(value:GetAttribute("Position"), "}","")
		local NewString2 = string.gsub(NewString, "{","")
		local NewString3 = string.split(NewString2,",")
		local NewString4 = string.gsub(value:GetAttribute("Size"), "}","")
		local NewString5 = string.gsub(NewString4, "{","")
		local NewString6 = string.split(NewString5,",")
		local NewString7 = string.gsub(value:GetAttribute("storesize"), "}","")
		local NewString8 = string.gsub(NewString4, "{","")
		local NewString9 = string.split(NewString5,",")
		NewNote.Position = UDim2.new(table.unpack(NewString3))
		NewNote.Size = UDim2.new(table.unpack(NewString6))
		NewNote:SetAttribute("storesize",UDim2.new(table.unpack(NewString9)))
		NewNote.assets.Velocity.Value = tonumber(value:GetAttribute("Velocity"))
		NewNote.LeftScale.Velocityframe.Size = UDim2.new(math.clamp(NewNote.assets.Velocity.Value/16,0,8),0,NewNote.LeftScale.Velocityframe.Size.Y.Scale,0)
		local notedescription = NewNote.RightScale.NoteDescription
		notedescription.ImageLabel.Velocity.Text = tostring("Velocity: "..NewNote.assets.Velocity.Value)
		NewNote.Parent = track
	end
end

game.ReplicatedStorage.Remotes.Read3.OnClientEvent:Connect(function(plr)
	local a = os.clock()
	loaded = false
	local data = game.CollectionService:GetTagged(player.UserId)
	if player ~= game.Players.LocalPlayer then return end
	script.Parent.Parent.processing.Visible = true
	for k=1, #tracks do local track = tracks[k]
		if not track:IsDescendantOf(script.Parent.canvas) then continue	end
		Read2(track,data)
		if os.clock() - a >= 1/60 then
			wait()
			a = os.clock()
		end
	end
	loaded = true
	script.Parent.Parent.processing.Visible = false
	game.ReplicatedStorage.Remotes.FinishLoading:FireServer(script.Parent.Parent.station.Value)
end)
1 Like

you dont need thousands of guis for this, you can just reuse them, whenever it goes off screen just reposition it and use it as another one

This might be useless feedback, but couldn’t you make it where you don’t have to generate thousands of UI elements? Where are these thousands of UI elements coming from?

it can either be generated via datastore or a link to a midi file online

Okay, but what I mean is why are there thousands of UI elements being created? You definitely could reduce that.

its supposed to be editable and it runs 60 fps when its done loading because i have a render system. plus who knows if a player wants to import a large file into the game to play, or they want to make a song themselves and end up creating a lot of image buttons for it

Don’t quote me on this, but larger files = more to download which is why Roblox limits their file sizes for audio and such – however, I haven’t really read your code entirely, but I know that there shouldn’t be any instance where you have thousands of UI elements at 1 time or else you could reduce that.

You could iterate through a table which contains data for whatever they’ve created and check the distance from a starting point, if less than that, disconnect connections you may have and create connections you may not have for those extending.

ive created a render system for that. everythis is smooth, event the playing. its only loading that lags. using task.wait or so makes the loading process a lot slower

im gonna be honest, thats the dumbest way to load something i have ever seen, but if it works then i guess its ok.

if you only want to get rid of the lag spikes when its loading then my last suggestion is to increase the fraction above from 1/60 to 1/120 or 1 / any number, the bigger the fraction, the longer itll take but the less laggy itll be.

also depending on what type of table you are using you may be able to replace pairs with ipairs which is much faster

if that doesnt work then sorry i cant help you