Hi Developers,
In our initial release of Parallel Luau, there were many cases where communicating with an Actor or associated scripts could be inconvenient. Today, we have introduced two key features to make communication more convenient and to open up new ways to communicate efficiently; Actor Messaging API & SharedTable.
Previously, communication required storing state directly in the DataModel, or transmitting state using existing mechanisms (e.g. BindableEvents). So, while communication was possible, it was often inconvenient, and having Actors accessing shared state wasn’t really possible when running in parallel.
What’s New?
Actor Messaging API
The Actor Messaging API allows a script to send a message to an Actor within the same DataModel. Messages are sent asynchronously (i.e. the sender doesn’t block until the receiver receives the message).
Any script may send messages to an Actor, but only scripts that are descendants of an Actor are allowed to receive those messages. Since there are many different kinds of messages that one might want to send to an Actor, the messaging API uses a “topic” to identify the kind of message being sent and received.
Example message sender:
-- Send two messages to the worker actor with a topic of "Greeting"
local workerActor = workspace.WorkerActor
workerActor:SendMessage("Greeting", "Hello World!")
workerActor:SendMessage("Greeting", "Welcome")
print("Sent messages")
Example message receiver:
-- Get the actor this script is parented to
local actor = script:GetActor()
-- Bind a callback for the "Greeting" message topic
actor:BindToMessageParallel("Greeting", function(greetingString)
print(actor.Name, "-", greetingString)
end)
print("Bound to messages")
SharedTable
Currently, scripts running under different Actors don’t have a way to share data efficiently. They can send data to one another, but sending data requires that data be copied. If large amounts of data are involved, sending the data can be inefficient. For many use cases, it is desirable to allow direct sharing of data. For example, multiple Actors may need to work on a common world state that is not stored in the DataModel. If this state requires a large amount of data it could be inefficient to send a copy to each Actor.
To support this, we are adding a new data type to Roblox called SharedTable. A SharedTable is a table-like data structure that can be accessed from scripts running under multiple Actors. Sending a SharedTable to another Actor (e.g., via the new Actor Messaging API) does not make a copy of the data; instead, SharedTables are effectively shared “by reference.” Multiple Actors can update the same SharedTable in parallel.
SharedTables have an API that is fairly similar to standard Luau tables. For example, they support reading and writing values using a key, with v = st[k]
or st[k] = v
. There are some restrictions on the kinds of data that can be stored in a SharedTable–notably, all keys must be either a string or a non-negative integer. SharedTables can be cloned, and clones use structural sharing to make them very inexpensive (data is not copied when a SharedTable is cloned).
Here are a few simple examples:
-- SharedTables can be used much like ordinary Luau tables:
local st = SharedTable.new()
st.a = 100
st["b"] = 200
st[1] = 300
-- SharedTables can be inexpensively cloned:
local clone = SharedTable.clone(st)
-- A global SharedTableRegistry is provided for "sharing" SharedTables:
local SharedTableRegistry = game:GetService("SharedTableRegistry")
SharedTableRegistry:SetSharedTable("MyData", st)
local myData = SharedTableRegistry:GetSharedTable("MyData")
myData[2] = 400
You can find out more about the features supported by SharedTable, along with concurrency and atomicity guarantees and a variety of code samples in the SharedTable documentation.
Support for this new data type has been added to Roblox Studio. Printing a SharedTable will cause it to be displayed in the output window as you would expect.
Printing a SharedTable:
Changes and Improvements
Scheduling Changes
For this release of Parallel Luau we made changes to scheduling which have these benefits:
-
We modified parallel signal scheduling so that parallel scripts run at the same “resumption points” as deferred threads. This means that the scheduling of all signal types is much more consistent now.
-
This also means that if a Luau script performs a “ConnectParallel” call on a RunService event, the parallel callback will occur during that engine phase. Therefore scripts now have much more control over when parallel callbacks will execute during the frame.
We execute “deferred” Luau signals many times during a frame, so running parallel scripts only once per frame seems inconsistent.
Internal engine systems may also want to execute Luau scripts in parallel but require those scripts to run at specific times during the frame. Of course, if we want to do this internally there is a good chance that Roblox developers will also want this ability.
More Thread-safe APIs
A lot of the discussion so far has been focused on improvements to the base programming model available to scripts. However, having a great programming model still isn’t very useful if scripts running in parallel can’t call the APIs that they need to use. So another area of improvement we focused on recently was making more of Roblox APIs thread safe so they can be called from scripts running in parallel.
Here’s a list of some of the APIs we have made accessible to parallel scripts as Safe since our initial release:
Click here to view the list.
- Instance:GetActor
- BasePart:GetNetworkOwner
- BasePart:GetNetworkOwnershipAuto
- BasePart:CanCollideWith
- BasePart:GetVelocityAtPosition
- Workspace:GetPhysicsThrottling
- Workspace:GetNumAwakeParts
- Workspace:GetServerTimeNow
- Workspace:GetRealPhysicsFPS
- Player:GetNetworkPing
- Players:GetPlayerByUserId
- Humanoid:GetStateEnabled
- Humanoid:GetState
- Terrain:GetMaterialColor
- HTTPService:JSONDecode
- HTTPService:JSONEncode
- HTTPService:UrlEncode
- HTTPService:GenerateGUID
- RunService:IsServer
- RunService:IsClient
- RunService:IsStudio
- RunService:IsRunMode
- RunService:IsEdit
- PVInstance:GetPivot
Roblox has a large number of APIs, and we realize that there are still a lot of APIs and properties that can be made thread safe. Please let us know on the dev forums if there are specific APIs that could be made more accessible to increase your adoption of Parallel Luau. Knowing what APIs are the most valuable to make accessible (whether that is Read Safe, Local Safe, or Safe) from Parallel Luau will help us prioritize work to make the necessary changes.
Improving Some Behavior from Our Initial Release
Over time, we’ve realized that some of the task library APIs have behavior that can be unexpected or surprising. As part of this release, we are making the following changes.
task.synchronize() and task.desynchronize() may now only be called from scripts that are descendants of an Actor. Previously, it was possible for a script that was not a descendant of an Actor to call these APIs. The resulting behavior was likely surprising: A script that is not a descendant of an Actor can never run in parallel, so if such a script called task.desynchronize(), that call would have no effect and the script would continue running in serial.
We will be changing the behavior of these APIs so that an error is raised if they are called from such a script.
task.defer(), task.delay(), and task.wait() now resume in the same context (serial or parallel) that they were called in. Previously, these APIs would all resume in the serial context, even when called from a script running in the parallel context. This resulted in surprising, unexpected context changes. Ideally, all context changes should be explicit, e.g., via a call to task.synchronize() or task.desynchronize().
We will be changing the behavior of these APIs so that they will always resume in the same context that they were called in. When one of these APIs is called from the parallel context, the script will be resumed in the parallel context. When called from the serial context, the behavior is unchanged, and the script will be resumed in the serial context.
While these are breaking API changes, we believe they will make the API behavior more consistent. We have metrics that indicate that only a handful of experiences will be impacted. To reduce the impact and help you to update your scripts, today we are only enabling warnings for scripts that would be broken by these changes. The warnings will appear in the console, along with other diagnostic messages. We will follow up with another post announcing a date for the behavioral changes in the near future.
Additional Information
We have also made some optimizations to reduce the overhead in Parallel Luau to improve performance. For example, some of the thread-safety checks decreased performance in our micro benchmarks even for scripts not running in parallel.
We have also made numerous minor fixes for issues that impacted Parallel Luau.
We have updated and expanded our documentation for Parallel Luau:
- An updated overview of Parallel Luau:
- Added messaging API documentation to Actor:
- SharedTable/SharedTableRegistry API documentation:
- Added more detailed documentation for our task library:
What’s next for Parallel Luau
We know that there is still more work to do to improve Parallel Luau ever further. Here are some areas we hope to address in the future:
- Provide more tutorials for developers to see how Parallel Luau can be used in their experiences
- Continue to optimize Parallel Luau to reduce overhead and improve performance
- Make even more APIs available from parallel scripts
- Work on fundamental internal engine changes to enable more parallelism
- And of course address your feedback…
Availability
Parallel Luau Version 2 features are available in the Roblox 576 (and later) release. You may begin trying out these features in Roblox Studio immediately. However, please be aware that some mobile and console platforms may not be updated to this release at the time of this announcement. Those platforms will be able to use Parallel Luau Version 2 features as they update to the 576 release in the coming weeks.
Feedback
We are looking forward to hearing your feedback on Parallel Luau. Please let us know what you like about our latest release and what areas are causing difficulties. We’d love to hear about how you are using the system as well as what future plans you may have. Your feedback is instrumental in guiding what we do next!
Thank you.