Parallel Luau [Version 2 Release]

Nevermind, the whole AddToFilter issue was because of some oversights in my code. It works well to be honest. Tho any chance for perhaps a ClearFilter method? Could maybe save some time by just clearing a single one out every time rather than having to make new RaycastParams every time.

Also would it be possible to have GetSharedTable() return nil if the given string wasnt an entry created for it already? Would probably be more convenient than it returning an empty table.

3 Likes

Typically you should be deleting player data from tables when they leave the game in-order to clear up memory anyways, but if there are any cases where you do not, I cannot imagine why the same player rejoining and occupying the same key would be a bad thing.

Further, you can deserialize the UserId back into the Player instance for the API calls you mentioned quite easily with the Players:GetPlayerByUserId() method.

My point here is that while yes, it may be somewhat inconvenient at times, this limitation likely won’t actually prevent most use cases and is probably quite important from a performance standpoint.

My understanding is that parallel actors run in different Luau VMs, so enabling non-primative keys like tables and userdatas (Instances) would require synchronization of the internal identifiers for these datatypes which would create huge overhead if it is even feasible to begin with. Not worth it for convience in my eyes, but who knows, maybe it will be supported down the line.

If you have any further questions or want to continue discussing, feel free to send me a message. I don’t want to clog up this topic too much.

3 Likes

It is significantly slower than just accessing a normal table, but if you compare it to sending a table through a BindableEvent like you previously had to do, the results are a little better. My testing is showing iterating over an entire SharedTable takes approximately the same amount of time as sending it’s normal table equivalent through a BindableEvent.

cc @Fluffmiceter

edit: I should mention that this assumes you are just reading, writing by index, or writing with the SharedTable.increment() function. Using SharedTable.update() takes (understandably) significantly longer, about 10x the other methods.

2 Likes

Much anticipated and needed update: :+1:

I’ve updated my ActorPool module to support the new parallel luau 2 features.


Example

local ActorPool = require(game:GetService("ReplicatedStorage").ActorPool)

local myPool = ActorPool.new {
	baseModule = script.BaseModule,
	poolFolder = script.Actors,
	min = 1,
	max = 2,
	retries = 10,
	retriesInterval = 0
}

local myConnection = myPool:take()

local numsToAdd = SharedTable.new { 2, 4, 6, 8 }
myConnection:run(numsToAdd)
print(numsToAdd["total"]) -- PRINTS: 20

script.BaseModule

return function(numsToAdd)
	local total = 0
	for _,num in numsToAdd do total += num end
	numsToAdd["total"] = total
end
7 Likes

My use case involves only reads so hopefully performance in this case will be addressed with future updates. Maybe it would be best to copy over the data to each actor during loading so each VM can access the table at normal speeds? My concern is with the amount of memory that might consume, right now my level data takes about ~100MB in script memory.

2 Likes

I recall arseny talking about it a while back, it’s based on the average CPU usage of your game. Server resources are dynamically introduced to you the more you use them.

EDIT : Found it

5 Likes

Hello! I ran into an interesting issue, not sure if its a bug or I’m just not understanding something.
My setup: A single actor with the following script in the workspace:

task.desynchronize()
local r = 0

while(true) do
    print("busy work")
    for j=1,3000000 do --busy work, about 30ms
        r+=math.random()
    end
    task.wait()
end

What I expected: This loop would run completely parallel to the main game

What happens: It appears to block execution of the main thread, as though it is not parallel at all. eg: If this runs at 20fps, the whole experience in studio runs at 20fps.

Sorry if I’ve done something daft, but what is going on?

4 Likes

Tables are converted to a mutable SharedTable with limitations of a SharedTable.
Functions cannot be stored because of cross-VM limitation you mentioned.

2 Likes

I’ve responded to linked topic, to reiterate here, Terrain:ReadVoxels is callable in parallel and there are no mutex locks.
No plans for Terrain:WriteVoxels right now.

3 Likes

Parallel Luau is made to run many per-frame tasks in parallel with each other, not to run long-running tasks in parallel with the engine.

We are exploring some options for long-running tasks, but we haven’t decided anything concrete to make a promise.

2 Likes

Amazing update! I’ve recently started incorporating Parallel Luau into all of my new projects and found having to use BindableEvents to get data in and out incredibly annoying, so these new additions are greatly appreciated, but I find the inability to use BindToMessage outside of actor scripts a bit disappointing since I would really like to use it to also get output out of Actors and not just input, are there any plans to enable it for use outside of Actor scripts?

4 Likes

Okay thanks for the answer :slight_smile:

So now that actors get checked and resumed multiple times per frame, is there a way to execute code after all of the actors on a frame have run?

2 Likes

If you need to create one with each call then don’t bother. It’s a semi-solution to having to serialize large tables back and forth when communicating between actors. You’re meant to keep the same table semi-permanently and read/write to it as you need. You can create a very large SharedTable almost instantly by calling SharedTable.new(originaltable) though.

I’d really like to see them expand their API. I’d like to see a ToTable method, maybe also some level of access to mutex to speed up access. My guess is the overhead currently comes from it having to lock and unlock the shared table every time you edit a value, and there’s hardly any reason to do that 10 times in a row when you want to add 10 values. Maybe some kind of a bulk write method?

1 Like

So what I believe is the case is a SharedTable lives in a single area of memory that multiple Actors can access?

Yes.

1 Like

Thanks for the feedback! SharedTables are definitely slower than built-in (non-shared) Luau tables. We’ve measured about a 10x performance difference for various usage patterns. Some of the overhead (about 1/3 of it) is due to fundamental synchronization costs. The remaining overhead is largely the cost of moving data between the Luau VM and the “shared state” (for example, strings need to be copied into the Luau VM when they are accessed). A lot of optimizations that make built-in Luau tables fast can’t be used when data is shared across Luau VMs (or, at least, many of them require substantial work).

That said, there are definitely opportunities for reducing some of the overhead, and that’s something that we intend to look at over time. For the moment, we believe there are a lot of scenarios where the current performance characteristics are “good enough.” We’re very interested in seeing how people start using these new features so that we can target future improvements where they’d be most valuable. We appreciate any and all feedback in this area.

7 Likes

This sounds great and all, but I’m curious if there is any use cases of SharedTable outside Parallel Luau, and whether it is advisable or not. It sure is global state and everyone knows how bad unmanaged global state can be, but again this might improve (or not) cross-script communication. (unless ofc, im being an idiot and this feature is only accessible in Parallel Luau)

Thanks; we appreciate this feedback. The current restrictions on key types are a compromise–we expect these types of keys to be the most commonly used and most useful, and they were the easiest to implement efficient support for.

Due to the “shared” nature of SharedTables, there are certain types of keys that we cannot support. For example, we could not support using a Luau table as a SharedTable key. But there are certainly other types of keys that we could consider supporting in the future if there is demand for them and if we are able to implement support efficiently. For the present, we expect that even with support only for integer and string keys, there are a lot of use cases that will benefit from this feature.

2 Likes

Vector3 keys would be my next request :slight_smile: also instances as keys is hyper useful.

4 Likes

You can, but you’re better off using ModuleScripts (or even _G if you like to play dangerous) for sharing environments between the same execution context. Like mentioned above there are performance implications with SharedTable and it should only be used for Parallel Luau because there’s no other feasible options.