Replicating modules with actors

Im currently trying to make my games start using a parallel lua to help with performance, alas, I ran into an issue.

I have a module that holds most of the players data, the issue is that I have a script running on a different thread (at least I think thats what its called) that needs to access the data inside of said module.

As a lot of you will know, every thread uses its own copy of modules basically, so the changes made in one thread wont replicate to the others. I think you can see how this is an issue.


So now Im here to ask what are some workarounds I could use to have the same effect as it replicating?
Any ideas would help a lot!
Thanks in advance :D

I’m assuming you are using a sort of OOP method of holding the player’s data. In that case you could use a BindableEvent that when called, returns the player’s Data you specified for. Not sure how effective that’ll be, I believe you’ll also need to make 1 BindableEvent for every player.

Also I’m fairly certain if you change a module’s data on the server script, the changes will apply for currently and future scripts that are requiring the Module script. So I’d like for you to specify more on

So basically, from my testing, and looking it up.

Every time you use task.dsync it creates a new thread (granted its in an actor, or something like that).

Every thread uses its own copy of a module, so all scripts in one thread have the same copy of a module, but in another thread, it would be a separate copy.

tl;dr modules dont replicate between different threads.


I think bindable events and/or bindable functions will probably work considering I only really would have to trigger it once every like 20-ish seconds or something (point is, not very often).

So I’ll give it a try and see how it goes!

Have you tried experimenting with Actor:SendMessage() and Actor:BindToMessage()? I feel that they could less heavy and more streamlined that bindables

Parallel programming in Roblox has seemingly hit a dead end at this point, especially since the introduction of outrageous restrictions to the server and client core usage. Sometimes you won’t even get any actors to run on separate cores in a live experience.

This, combined with the inherent overhead of memory locks and the VM reference boxing required to keep a scripting language sandboxed and safe makes any gains you could possibly achieve by utilizing parallel actors entirely pointless.

All you’ll achieve by copying modules or creating round-a-bout systems is use up more system memory. Maybe the stage for parallel programming will improve in the future, but for now I’d stay strictly with serial.

2 Likes

How?

You need a SharedTables for that.
To access them from actors (including desyncronized ones) use SharedTableRegistry:GetSharedTable(nameOfId)
Althrough if data is always static i would also suggest to freeze SharedTable instantly as it will prevent overhead that they create in loops.

What to do now?

Instead of relying on module you could move entire data structure to use SharedTables that do work like a DataStore keys kinda.

That so funny becouse i saw this post right after nerding Parallel Luau.:money_mouth_face:
Yeah kinda funny

1 Like

You just don’t have to use it in places where you should not. Main game logic will always have to run on serial regardless, and you should use parallel for more side tasks such as raycasting validation.
I agree that it is very limited, but it is limited for a reason: everything getting synchronized accordingly, and for me SharedTables is more than enough.
You should definitely give Parallel Luau a second try and view it from the other side.

There are a lot of good answers here, but I will reiterate on what @index_self said,

All of the solutions here will come with performance penalty. Moving data across parallel threads is costly, SharedTables are slow, Bindables and Actor:SendMessage() as well. I don’t have numbers, but I can tell you it is slow to the point it is likely going to be slower than serial execution

If you call a bindable or Actor:SendMessage() every 20 second, that could work? Be wary of lag spikes though (if you do it on the client), as the frame on which the bindable was called will be longer. The more data, the laggier it is

Parallel programming is mainly useful for easilyish parallelizable tasks, but even more so on roblox (due to the poor implementation and/or lack of support within lua). I would highly suggest reconsidering the use of parallel lua. I’d say good use cases for parallel lua is compression/decompression (or serialization) of massive tables (if you can separate it in chunks), raycasting rending engines, stuff like that

Often times, lag comes from the roblox engine, for example, I have a ski lift system that doesn’t use the physics engine, and CFrames each chair every frame, and most of the lag comes from updating the CFrame of the chairlifts, more than calculations. I tried paralleling it (before roblox nerfed parallel lua), and the gains were eaten by the overhead, it wasn’t faster

There is also the option of making each parallel thread compute the data instead of requesting it from other threads. This involves having the state of the game be deterministic, ie, every thread ends up with the same result (in your case, PlayerData) given the player’s actions, so in a sense, you’d have multiple servers running the same tasks, which sounds counter productive, but could actually improve performance if the tasks aren’t heavy

Could you provide some examples of what you want to use parallel lua for?

Also, my suggestions for optimizing games will always be the Micro Profiler. Without it, you are just blindly optimizing things. The script performance tab is garbage (for reasons…)

1 Like

Im currently using it to make it so all players actions are handled in a different thread, as Im making a fast-ish paced game and it seemed like a good idea. (Ofc this is the first time I’ve usued parallel lua so correct me if I’m wrong about any of this)


From second thought, if the above what I said is still a good idea, I can probably take the requests that get the players data out of that thread and into the main one.

On that subject, do you have any ideas on sharing player data across the client and server? Cause thats currently the whole issue behind this, is just not having a good way to go about it.


But yeah thats what Im currently doing, if you have any more questions feel free to ask! And thanks again for all your help!

:D

1 Like

If we are talking about your typical handling of player actions, then it’s probably a poor candidate for parallel lua

If you eliminate the communication happening between threads, you eliminate a big portion of the overhead. I think scripts that run in parallel without communicating with others don’t have a lot of overhead, but I’m not sure

What are you looking for? Performance, or abstracting the process? I’ve got a unique way of handling data replication here, it’s not for performance but rather ease of use

Cross-thread communication

Under the multithreading context, you can still allow scripts in different actors to communicate with each other to exchange data, coordinate tasks, and synchronize activities. The engine supports the following mechanisms for cross-thread communication:

You can support multiple mechanisms to accommodate your cross-thread communication needs. For example, you can send a shared table through the Actor Messaging API.

Also do note, using Parallel Luau will most likely not help you in your case, it’ll probably make it worse due to added overheads and costs of communicating between Luau VMs.
And to write to the DataModel you need to run serially anyways.

What kind of work are your scripts doing, are you actually running into performance issues?

1 Like

Im currently not running into any performance issues, but I figured I should probably figure this stuff out before hand to save myself some time.

Thanks on the insight!

Probably something more performant, but still easy to use. Kinda in the middle. As it would be for the player accessing data, and maybe information about the server ( an example might be the current gamemode, or something like that)


So I take it the general idea right now is to just not use parallel lua for this?
In that case, what are some tasks I should use parallel lua for?

Thanks again!

1 Like

You should only use parallel luau for heavy computing tasks that do not need to perform many datamodel write operations, such as complex math calculations, or functions that support multithreading, like raycasting.

2 Likes

I have a question, honest question…Why do some programmers like to Over Engineer stuff and stuff by claiming by writing code some way will make it be faster by a speed you won’t even notice(0.0002) seconds lol

1 Like

Some people just like to optimize things to the best it can possibly be, sometimes its a 0.002 second difference, but that 0.002 second difference can add up, or something like that.

Performance is nice :D


At least thats my own opinion on it, I dont have a lot of facts, but thats just a theory. A programming theory.

1 Like

I totally feel ya, but considering experts in the tech industry advise that rather than wasting time optimizing working code why not actually build features and focus on optimization later on

1 Like

The way I do it is, well I generally try to make things optimized if it’s easy to do so, otherwise, I optimize if I notice that something is running slow, by looking through the micro profiler

Yeah, but often times, that 0.002 second difference only happens a handful of times, leading to no meaningful difference. But in other cases, a small difference can be huge when repeating a task multiple thousands of times, one good example is a signal library versus RBXScriptSignals, if you abuse signals a little
Signals is also something I’d put into the easy to optimize category, it’s easy to use (often has more features even), and is faster

1 Like