Performance issues

Currently, one of the experiences I’m part of is experiencing some not-so-great performance. The server FPS/performance starts dropping dramatically very quickly, even without much user interaction.
I have read many things on how this could be fixed, but I just do not understand any of it.
I also looked at gcinfo(), but I don’t know what it means or does.

[120 FPS limit]

Screenshots





Foreground scene screenshots

image
image
Screenshot 2025-04-08 201257

Microprofiler screenshots of spikes

Screenshot 2025-04-08 201237
Screenshot 2025-04-08 201244

Screenshots from a big lag spike

Screenshot 2025-04-08 201602
Screenshot 2025-04-08 201608
Screenshot 2025-04-08 201615

Over time, these lag spikes increase and happen much more often, and some things no longer run smoothly (such as tweens, etc).

Examples



Watch Roblox VR 2025.04.08 - 20.17.37.02 | Streamable
Watch Roblox VR 2025.04.08 - 20.17.50.03 | Streamable

After about 20 minutes, the server FPS has dropped dramatically from 60 to anywhere between 15 and 45 FPS
image
Screenshot 2025-04-08 202519
(screenshot from Adonis “!serverlag” command)

image
(screenshot from Adonis “!serverinfo” command)

About 40 minutes in:

Client untracked memory:

Client general high values:


Some profiling:
2.html (594.0 KB)
1.html (820.1 KB)

This is the microprofiler after about an hour:


image

Everything runs perfectly in Roblox Studio, but I did read that it is because it is a local test and not a Roblox server.

8 FPS moment:

Screenshot 2025-04-08 205412
Screenshot 2025-04-08 205430

Performance is at around 30 after the 8 FPS lag:
Screenshot 2025-04-08 211136
Screenshot 2025-04-08 211140

Streaming is enabled:
Screenshot 2025-04-08 205450
image

Screenshots from another developer

image




image
image


A huge lag spike, said developer experienced:


(those were in Studio ^)

Experience link

I don’t really know what else I can add to this post. If you have questions or need extra information, please ask.

Also, how bad is not disconnecting events?

ᵀʰᶦˢ ᵗᵒᵒᵏ ʷᵃʸ ᵗᵒᵒ ˡᵒⁿᵍ ᵗᵒ ᵗʸᵖᵉ

EDIT

I’ve also noticed the following resources, and I was wondering if any could be useful;
https://devforum.roblox.com/t/performance-issues/3598431
https://devforum.roblox.com/t/untracked-memory-becoming-major-source-of-games-memory-leak-issue/258605
https://devforum.roblox.com/t/psa-connections-can-memory-leak-instances/90082
https://create.roblox.com/docs/reference/engine/classes/Debris

Have you got any nested connections? So like a property changes and you start a render stepped or while loop? Disconnecting events can become a super big issue as roblox’s garbage collector while superb takes some time to kick in

1 Like

Roblox as a whole does an excellent job with their automatic garbage collection on objects you are no longer referencing anymore.

The general rule of thumb is that you should ONLY disconnect signals you aren’t going to use anymore.

From how it looks, you have a script that has a large execution time. You can isolate different parts of your scripts using the debug library.

debug.profilebegin("Test Code") 
-- Your code goes in-between this
debug.profileend()
1 Like

Sorry but whats a nested connection?

Code which looks like

Object:GetPropertyChangedSignal("Hey"):Connect(function()

 RunService.RenderStepped:Connect(function()

 -- Unless you disconnect the connection this will always run

 end)
end)
1 Like

I’ll do that but first we will work to look through the scripts to find one… it was back from the ‘time of free models’
Thanks for suggestion and I’ll get back to you when we find it

I don’t think we currently have any but if I do come across a need for one, or one, how could I disconnect it?

You can create a variable outside of the scope you defined the second signal from.


local Signal = nil
Object:GetPropertyChangedSignal("Hey"):Connect(function()
 if Signal then 
    Signal:Disconnect(); 
    Signal = nil 
 end
 Signal = RunService.RenderStepped:Connect(function()


 end)
end)

Actually, I glanced over it initially. This is more proper.

2 Likes

Building off of that, signals will run indefinitely unless the script that connected them is destroyed (terminating the thread), or the signal itself is disconnected.

It’s very important to keep a reference somewhere to a signal you connect at all times so you can clean it up manually when you need to.

Roblox’s garbage collection system does not clean up connected signals.

1 Like

I found a script with this in it:

while true do
	for i = 1,#imgs do
		script.Parent.Image = "http://www.roblox.com/asset/?ID="..imgs[i]
		wait(0.03)
	end
end

And I’ve just deleted it as it isn’t needed (although I doubt it did much harm)
We’ve gone through the 900 no name scripts in workspace and just deleted and disabled some
Ill check micro profiler after studio starts responding again
image
since I probably am trying to close about 200 scrips

So things like :Connect() make script signals and they stay forever unless disconnected?
Is so, can that cause memory leaks?

Yeah it’s a good pratice to disconnect them after they are not anymore useful.

1 Like

It looks like one of those animated gif loops.
You can use a module-script (or a collectionService loop if it’s just for specifically tagged Instances) for repeated code instead so you don’t have to mass-replace 200+ scripts.

1 Like

Should this be done for non-nested connections too?
If so, what would that look like?

Is there a way to see what script takes the longest to execute and provide the path to the script?

It depends on what you’re connected to, really.
The Connect method always returns a connection so you can create a variable that holds onto the signal and you can disconnect it later.
Calling the :Destroy() method on an Instance will disconnect all the connected signals to it, so you don’t have to reference the signal if you’re going to destroy that instance later anyways.

1 Like

If I may ask, what if anything does the following mean?
image


since there are many of them.

And is the Async event part of Roblox or is that from a script or something?

You have a script (or two) connected to the “Heartbeat” signal under RunService.
They’re taking up a lengthy amount of time (hence the long bar with the “Heartbeat” under the MicroProfiler.)

There’s a very useful guide on actually utilizing it so you can easily discern issues regarding your game’s performance.

1 Like

Async is short for Asynchronous, which I assume means you have a thread running some code somewhere so the rest of the script continues running parallel to the other code.

1 Like

image

image

So things such as that are covered in the walkthrough or are they from scripts?

EDIT: I will read the micro profiler walkthrough before asking more