- Home /
Lowered general performance with Threads
I am trying to get threading working in Unity. I have a heavy task which has all the data it needs ready early in the frame and doesn't need to be done until the end of the frame, so it would make sense to have it just run in parallel while the rest of the game logic is resolving.
I have tried the new Jobs system, which works, but putting and withdrawing all the data from the nativeArray ends up taking 3x as long as the actual operation, so it's not a solution. Instead I moved on to raw C# threading, and came across some unusual behavior.
When putting the heavy task on another thread, main thread slows down to about half speed.
On the left you see the Heavy Task, which as expected drops down to 0ms when threading is turned on. On the right you see another random task. Pretty much all scripts have a 100-150% increase when the threading is toggled on, which drops back to normal immediately when it's toggled off again. The increase doesn't seem to be concentrated anywhere in particular but trickles down the entire hierarchy.
It happens whether I use a continuous while(true) thread or a thread pool where I start a thread each frame. I have tried throwing out safety and running the thing without any locks at all (in case the locks were halting the main thread), to the same result.
Another thing to note, with threading the little notches on the Unity worker threads appear... sparser? Could be a clue, or the causality is the other way around and it's just an artifact of the main thread being slower and making requests less often.
Please please please, if you have any idea give me a nudge in the right direction.
Thank you.
Answer by JLJac · Jun 07, 2018 at 05:39 PM
After much research I might have figured it out. It seems that any repeated method calls in the new thread (I had a bunch of Mathf.Lerp - beware, even simple things like Clamp or Max etc seem to cause it!) will cause the weird slowdown on the main thread. I suppose this is because the method calls somehow need to check back between threads or are referring to some common object or similar. Maybe there is a lock on Mathf?
If the code inside the thread doesn't employ any method calls, it seems to be able to spin away on its own without getting in the way of the main thread.
On a slightly ironic note the exclusion of method calls made my code so much faster that I don't even need to thread it any more. But, knowledge gained ~
I can't believe how stupid I was - it's the Deep Profiler. It's completely natural - each time a method is called anywhere, the Deep Profiler must be notified, and some kind of lock is utilized. $$anonymous$$aking it so that if 2 threads are running in parallel, they have to wait for each other every time they reach a method call, making it take approximately as long as it would have to just run them one after each other. With the Deep Profiler disabled, I do get the expected speedups from parallelism.
Nice find (points awarded ;) )! This is useful for future when profiling multi-threaded code. And it's good to remember that profiling is not without its performance overhead!