Should I run my anticheat script in parallel? If so how?

I have an anti-cheat script that starts as soon as the players character is added and runs checks for flying, noclipping, spin hacks, etc. It works pretty well but even after my optimizations, I still get script activity spikes like up to 5%.

I’ve heard that anything past 3% can start to cause chat lag or other service lag and I was just curious how can I run this script in parallel to hopefully get rid of some of the lag?

Currently my script loops through a table of player characters and performs checks on them. Something like this:

for i,v in pairs(PlayerProfiles) do
-- do a bunch of heavy math to check for speed hacks, etc
end

How would I convert a table iteration into something parallel? Is it even possible for my use case, if so, will it reduce high script activity?

You’d create separate Actor instances for e.g. each Player, with the cheat detection code in a Script inside the Actor. Splitting the work up per Player seems like a good idea, because checking for Player A shouldn’t need to access or mutate the state that’s relevant to checking for Player B.

1 Like

Where should I place the actors? Should I have a folder under serverscriptservice dedicated just for them?

This is probably a dumb question but if I were to stick them all under one actor, would the performance benefit be less than having one for each player?

Would spawning a coroutine and desynchronizing each one of them would work well? Wait for each parallel thread to finish (wait for the coroutine to be dead, just use a bindable event or something that tells the main loop to continue). I assume you are looping and waiting a certain amount of time before checking players again. So, you should wait for each coroutine to finish and then execute again all code. Idk if this will be performant but try.

I really don’t know how actors are still used, so yeah. I just know about desynchronizing and synchronizing.

Coming back to this now, one actor, multiple scripts and using ConnectParallel is definitely the right move for my task. Even with a single Heartbeat connection with nothing inside of it, the script activity could jump to 0.3% without using what I just said.

Originally I had one actor and one script, which could essentially slow down the script when iterating through ~20 players, causing false positives. I avoided it by using task.spawn but parallel lua seems like a much more reliable option.

I tried one script and actor per player, however it still drove up script activity when it got to around 20 players. However with one actor and a script per player (under the same actor) it works perfectly. No slowdown and no script activity spikes.


20 scripts not using Parallel Lua.
image

20 scripts using Parallel Lua. (ALL SCRIPTS UNDER ONE ACTOR)
image

20 scripts using Parallel Lua. (ALL SCRIPTS UNDER ITS OWN ACTOR)
image

All scripts had this context:

local a = 0
game["Run Service"].Heartbeat:ConnectParallel(function(DeltaTime)
	a+=1
end)

Nothing heavy really, but still worth something.


Back here for the final time I promise, this is just for any possible lurkers that are interested in parallel lua but don’t know if it’s worth the switchover.

This is my anticheat with 8 players with parallel lua enabled: (Note that it never reached over 0.5%, it always stayed inbetween .488 and 0. Rarely reaching .488)
image

Here’s the same anticheat without parallel lua: (Note that this reached up to 1% per player, the screenshot just didn’t get that)
image

While to be fair there are differences in the scripts that probably make the parallel lua run faster not because it’s parallel but because I could create more optimizations just because it was parallel, it’s pretty insane how much of a difference parallel lua can make.

3 Likes

are you connecting a heartbeat to each script? or one heartbeat looping through the actors and sending each one a message

(sorry for bump)