Before I start I’m going to address a few things:
This isn’t exactly how this works. Regardless of how many threads are running you are enacting the same processes either way. You could defer 100 threads from an individual script to the same end result. Roblox runs about its task scheduler, if something is holding up the task scheduler because its calculations take time- there will be a delay regardless of how many bazaar scenarios you try to fix it that don’t directly address the problem.
This would have the opposite effect of what you think it would have. task.wait() is directly equivalent to RunService.Heartbeat:Wait()- this means that every single heartbeat that the task scheduler cycles will run these changes. IE- you are running this more often = more consistent processing = > chance of lag. That doesn’t mean that it isn’t part of the solution, it just means it doesn’t cause less “game lag”.
cpguy is correct in saying that you should transfer from wait
. Not for that exact reason that they stated- but because global wait is either deprecated or on-track to receive deprecation. I can’t keep up with deprecations so consistently. Working more directly with Roblox’s task scheduler gives you more control over your game and is in general better.
Okay, so what is the solution?
The first thing worth noting is that at the end of the day having so many parts cycling color is going to hold its innate performance regardless of how you handle it. You will need to accept that. That said, you can benchmark which solution works best fairly easily (use os.clock()-timestamp on each option and weigh its performance). Also keep in mind that certain things will process heavier than others. Semi-tansparent parts process heavier than solid parts. I imagine neon would impact processing negatively. Etc…
I would personally steer clear of TweenService, but that’s just my opinion, that many variables and that much code clutter when working with a lot of parts just impacts readability to me. And I imagine that if you benchmarked it against most other choices you would see the difference immediately.
The best solution is going to end up being whatever does as little math as possible and can apply its changes fast. This probably means you’re going to want to manipulate the part’s color directly from the script. You can create a table of all applicable parts and who they belong to, or whatever else might be needed and just iterate across that, per task cycle, to achieve your desired result.
The other option, depending on the rainbow’s functionality, is to create a rainbow out of other objects than parts. For instance you could probably make a pretty nice Rainbow with an individual beam object. In fact if it’s at all possible I would steer you in that direction over a bunch of parts. It’s easier to manage and just makes more sense.
All this to say, if you learn about benchmarking code you can actually test and answer this question for yourself.