Last active
May 24, 2024 15:22
-
-
Save BrettRToomey/a1e32c2f99fbb9d34dd4bec8566e6d00 to your computer and use it in GitHub Desktop.
Apple Thread Priorities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pthread.h> | |
typedef struct Thread_Desc { | |
qos_class_t qos; | |
int relative_priority; | |
int sched_policy; | |
void *userdata; | |
} Thread_Desc; | |
pthread_t create_thread( void *(*callback)(void *), Thread_Desc *desc ) | |
{ | |
pthread_t thread_id; | |
pthread_attr_t attr; | |
pthread_attr_init(&attr); | |
void *userdata = NULL; | |
if (desc) { | |
int relative_priority = desc->relative_priority; | |
relative_priority = relative_priority < 0 ? relative_priority : 0; | |
relative_priority = relative_priority > QOS_MIN_RELATIVE_PRIORITY ? relative_priority : QOS_MIN_RELATIVE_PRIORITY; | |
pthread_attr_set_qos_class_np(&attr, desc->qos, relative_priority); | |
pthread_attr_setschedpolicy(&attr, desc->sched_policy); | |
userdata = desc->userdata; | |
} | |
pthread_create(&thread_id, &attr, callback, userdata); | |
return thread_id; | |
} | |
void *thread_entry( void *userdata ) | |
{ | |
return NULL; | |
} | |
int main( void ) | |
{ | |
/* | |
Most information from | |
"Tune CPU job scheduling for Apple silicon games" | |
https://developer.apple.com/videos/play/tech-talks/110147/ | |
Choosing a QoS class: | |
When choosing a QoS class, you automatically get the max priority | |
for the class. You can use the `relative_priority` to lower the | |
priority. `relative_priority` must be within [ 0, QOS_MIN_RELATIVE_PRIORITY (-15) ]. | |
Priority | |
Recommended usage Def/Max Min | |
----------------------------------------- | |
QOS_CLASS_USER_INTERACTIVE Per-frame work 47 -- 38 | |
QOS_CLASS_USER_INITIATED Async/inter-frame work 37 -- 32 | |
QOS_CLASS_DEFAULT Streaming/Longer deadline 31 -- 21 | |
QOS_CLASS_UTILITY Background download/compute 20 -- 5 | |
QOS_CLASS_BACKGROUND Might not run for long time! 4 -- 0 | |
Assigning QoS class to threads: | |
// Create thread with a given QoS class | |
pthread_attr_t attr; | |
pthread_attr_init(&attr); | |
pthread_attr_set_qos_class_np(&attr, QOS_CLASS_..., relative_priority); | |
pthread_create(&thread_id, &attr, entry_point, userdata); | |
pthread_attr_destroy(&attr); | |
// Change the QoS class for the current thread | |
pthread_set_qos_class_self_np(QOS_CLASS..., relative_priority); | |
Choosing a scheduling policy | |
When choosing a scheduling policy you need to decide if the | |
thread should be realtime or not. You need to be careful with | |
realtime threads to not starve the OS. | |
Realtime Description | |
------------------------------------------------------------------------- | |
SCHED_FIFO YES First come first serve, not time limited. Easy to starve the OS! | |
SCHED_RR YES Round-robin, time limited, tries to be fair | |
SCHED_OTHER NO Default behaviour on macOS, most fair | |
Example Configurations: | |
Realtime: | |
Policy QoS Class | |
---------------------------------------------------- | |
Main Thread SCHED_OTHER QOS_CLASS_USER_INTERACTIVE (prio 47) | |
Render Thread SCHED_RR QOS_CLASS_USER_INTERACTIVE (prio 45) | |
Workers (High prio.) SCHED_RR QOS_CLASS_USER_INTERACTIVE (prio 39-41) | |
Workers (Medium/low prio.) SCHED_OTHER QOS_CLASS_USER_INTERACTIVE (prio 38) | |
Long duration | |
Policy QoS Class | |
----------------------------------------------- | |
Workers (High prio.) SCHED_OTHER QOS_CLASS_USER_INITIATED (prio 37) | |
Prefetching/streaming SCHED_OTHER QOS_CLASS_DEFAULT (prio 31) | |
Other low priority tasks SCHED_OTHER QOS_CLASS_UTILITY (prio 20) | |
*/ | |
pthread_t thread = create_thread(thread_entry, &(Thread_Desc) { | |
.qos = QOS_CLASS_USER_INTERACTIVE, | |
.sched_policy = SCHED_OTHER, | |
}); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment