I have a bunch of controllers that use Heartbeat. I’m wondering if I should just have a single module run the heartbeat and run their code seperatly, like this:
My assumption would be it’s better as this, as it’s a single heartbeat. But I don’t know if doing a bunch in a single heartbeat is bad performance wise?
Sorry for reviving this post, however I wouldn’t want anyone to be misguided by it. It is generally better to connect specific scripts to RunService.Heartbeat individually, rather than using a single “master connector” that runs everything through a large loop unless you specifically need to control the order of execution.
Here’s a breakdown of why:
Multiple Connections (Recommended)
Parallel Luau Compatibility: Roblox’s modern engine can run separate connections to the same event in parallel using actors and RunService.Heartbeat:ConnectParallel(), utilizing multiple CPU cores for better performance. A master connector approach forces all the code to run on a single thread.
Readability and Debugging: Separating logic into different, purpose-built connections makes the code cleaner, easier to manage, and simpler to debug. If an error occurs in one connection, it is less likely to break the entire system.
Modularity and Control: Each script has control over when it connects and disconnects from the event, preventing unnecessary code from running when not needed (e.g., a car script only runs when the car is active).
Minimal Overhead: The overhead of multiple RBXScriptConnection instances is negligible unless you have thousands of them, which is unlikely in typical game scenarios.
Master Connector (Generally Discouraged) (Still ok if you have to)
Single-Thread Bottleneck: All tasks are crammed into a single thread, which can create a performance bottleneck and negate the benefits of multithreading. (Irrelevant if your code is not split up into actors anyway)
Complex Error Management: If one function within the master loop errors, you need an intricate system to catch it without stopping the entire loop.
Management Overhead: You would need to manage adding and removing functions to a table every frame, which can introduce its own overhead and complexity.
Best Practice
Use individual RunService.Heartbeat:Connect() calls for different systems or objects, and ensure you disconnect them when they are no longer needed to prevent memory leaks.
For core game systems that must run every frame, keeping the code inside the connections optimized and lightweight is key to good performance, how you organize your connections has minimal impact.
Really? I’m saying… events are minimal impact. I’m sure you’ll never make 100 RunService.Heartbeat:Connect() routines, but you could make 100 events without worry.
you must have worse machine than mine (GT610 i3-2100)
Theres not a existing universe where at 100 individual Heartbeat connections you lag.
Friendly reminder ECS runs on systems (individual heartbeats), and you can have hundreds of them, querying thousands of entities.
Run service is in a way an event, that is fired every frame. Some say its more of a loop because its happening repeatedly every frame, but I would say its more event like as you can subscribe and unsubscribe to it. So using multiple heartbeat is in my opinion event driven.
“Event-Driven” usually refers to responding to discrete, sporadic events rather than a high-frequency, frame-by-frame signal. Technically you are correct however.
I’m more talking about setting up an event that fires when triggered, instead of constantly checking at high-frequency for no reason when you could make it event-driven.
It’s pretty clear that was my point anyway. I’m not even sure why this would be questioned at all.
More of a ongoing hater wannabe bully thing I dared to say anything in the first place I guess..