Get SpatialOS

Sites

Menu
These are the docs for 13.3, an old version of SpatialOS. The docs for this version are frozen: we do not correct, update or republish them. 13.4 is the newest →

Console development on SpatialOS is currently in early stages, please see the console development introduction page for the current status.

Thread affinity

Thread affinity, or CPU pinning, enables the binding of a thread to a specific logical core, or set of cores. It prevents the operating system scheduler from switching threads amongst many cores, which can reduce performance in performance critical environments, such as console games. The worker SDKs now expose thread affinity masks, which enable users to pin internal SpatialOS threads to specific cores in the same way other game logic threads would be pinned in a typical game engine.

Why use thread affinity?

Consoles have a fixed hardware configuration which you can optimize against. This is in contrast to desktops or laptops, that must scale to arbitrary CPU configurations or OS schedulers.

Benefits of thread affinity:

  • Avoids load from SpatialOS networking having an impact on rendering, audio, AI job systems and other engine systems, and vice versa.
  • Improve performance by increasing the percentage of local memory accesses.

If a game studio has shipped console titles before, engine programmers may have an established setup for thread affinity spanning physics, rendering, networking, audio, AI job systems, etc. SpatialOS aims to accommodate this by exposing thread affinity parameters.

Usage

SpatialOS uses several long-running and temporary threads on each worker. Long-running threads are involved in sending and receiving network packets, processing incoming messages, handling command timeouts and reporting metrics. Temporary threads are involved in initial connection attempts and connection handling.

Thread affinity is configurable by passing affinity masks within the ConnectionParameters for each language SDK. Affinity masks are bit masks where setting 1 in the nth least significant position means the thread will be permitted to run on the nth core. Setting the affinity mask to permit a core index which does not exist is undefined behaviour, and we are not performing any checks at runtime whether the logical core count accommodates the affinity masks.

Thread affinity is only intended for use on PS4™ and Xbox One™, however we also provide support for Windows and Linux. macOS doesn’t provide direct control over thread affinity, instead the affinity mask provides a hint to the scheduler.

struct ThreadAffinityParameters {
  /** Affinity mask for threads related to receiving network ops. */
  uint64_t ReceiveThreadsAffinityMask;
  /** Affinity mask for threads related to sending network ops. */
  uint64_t SendThreadsAffinityMask;
  /** Affinity mask for short-lived threads. */
  uint64_t TemporaryThreadsAffinityMask;
};

Exposing the thread affinity configuration in this manner is a compromise between a single shared thread affinity mask limiting flexibility, and a thread affinity mask for each long running and temporary thread meaning we would introduce API breaking changes when adjusting our internal thread usage.

Specific language SDK syntax is available in the reference docs:

Example

Below is a code snippet example of setting the thread affinity of SpatialOS threads within the C++ blank project.

worker::ConnectionParameters parameters;
parameters.ThreadAffinity.ReceiveThreadsAffinityMask = 8;
parameters.ThreadAffinity.SendThreadsAffinityMask = 4;
parameters.ThreadAffinity.TemporaryThreadsAffinityMask = 2;

Here, this snippet sets the thread affinity masks for receiving threads to 8, sending threads to 4, and temporary threads to 2. These are bit masks; a bit mask of 8 is equivalent to the binary string 00001000 with the 4th least significant bit set to 1. This means that receiving threads inside the SpatialOS SDK will only run on your logical core indexed 4th on your target platform. Similarly, sending threads affinity mask is 00000100, and so these threads will only run on the 3rd logical core. Lastly, temporary threads affinity mask is 00000010, and so these threads will only run on the 2nd logical core.

Search results

Was this page helpful?

Thanks for letting us know!

Thanks for your feedback

Need more help? Ask on the forums