There are a few things to consider in order to determine if your game process threads are appropriately utilized and scheduled for the best performance.
- Frame pacing
- Multithreading and thread parallelization
- CPU core affinity
Many games and game engines use multithreading to divide CPU work into logical tasks, which may be run somewhat independently. One typical configuration is a game thread for input and game logic, a render thread for preparing and submitting objects to be drawn, and worker threads for other subtasks such as animations or audio.
We recommend parallelizing threads to take advantage of performance gains of multithreading. An example of this is a scenario where the game and render threads are running partially or fully concurrently on different cores. This won't always be possible, such as in cases with shared data dependencies; however, when possible, this may result in lower CPU times and thus potentially higher frame rates.
CPU core affinity
One factor that significantly affects the performance of your CPU workloads is how they are scheduled on the cores. This may be split into two components:
- Whether your game threads are running on the best cores for performance
- Whether your game threads switch between cores frequently
You may investigate CPU thread behavior under CPU Usage by enabling the
CPU in the profile config when taking a trace. By zooming into a section of
your trace <200 ms, you can view the individual processes running on your device’s CPU cores. Typically, small cores correspond to smaller indices (for example, CPU
whereas large cores correspond to higher indices (for example, CPU
Generally, when the game is in the foreground, persistent threads such as the game thread and render thread should run on the high-performance large cores, whereas other process and worker threads may be scheduled on smaller cores.
You may also observe whether your game threads switch between cores frequently, if your main and render thread change cores within a single CPU frame or between two consecutive CPU frames. This CPU behavior is likely an indicator that your game threads are not properly affinitized. Such core switches incur some overhead from the context switch and the loss of state with a core’s cache/registers, resulting in an increase in the length of your CPU frame.