I’m making a game in which the terrain is created procedurally. I put all the heavy computation in threads to let the game runs smoothly. Basically, the only thing I do on the main thread is to pass the newly created mesh data to some mesh renderers.
It works perfectly fine, as intended, and allows me to generate the terrain dynamically while keeping a frame rate > 100.
However, I’m not yet satisfied, because sometimes (about every 5s) the game lags (it freezes during maybe 300ms), which is extremely annoying.
I can’t figure out what is causing it.
I’ve already checked a few things:
I’ve almost no “lock” thanks to the way my application is designed, so I don’t think it can come from here.
I’ve only 2 background threads + the main thread and I’m running it on a quad core CPU. As far as I know, 3 is lower than 4 so the main thread shouldn’t idle because of a background thread.
When I profile the application I can see that lags are often due to GUI.repaint or CharacterController.FixedUpdate which is surprising as it should be fast.
My guess is that the main thread doesn’t have enough CPU-time left for itself and so some methods that should be fast take sometimes more than 300ms.
I’m also wondering if the Garbage Collector can be the cause of it (maybe the profiler can’t see it in a multithread context?).
My guess is that it’s garbage collection. So when you’re passing the newly created data I’m going to take a guess here. I’m guessing your copying data over to a “production” array or creating a new one when you update it which is how you’re passing your updated mesh data… again just a guess… but I’d be guessing you’re creating allocations there.
I start to really think this is because of GC. Overhead remains low because my terrain is separated into chunks which are quite small (ie. meshes don’t have a lot of vertices) and I make sure to update no more than one chunk per frame.
I made a test by making my program work on the main thread only (ie. not multithreaded) so the profiler can record everything (as you might know, the profiler ignores everything going on in threads). I can now see some big overheads due to GC. As GC stops all threads during a collection, I’m almost sure this is my problem.
Thanks Dustin for having lead me on this way.
I guess I’m going to have to do some optimization and object pooling. I will post some updates here to let you know if I get any significant result.
Just so you know, I can confirm it was the GC. Thanks to intensive pooling and some memory optimizations I finally got rid of frame rate drops. Now everything works like a charm
Thanks!