forked from OSchip/llvm-project
Add ThreadPriority::Low, and use QoS class Utility on Mac
On Apple Silicon Macs, using a Darwin thread priority of PRIO_DARWIN_BG seems to map directly to the QoS class Background. With this priority, the thread is confined to efficiency cores only, which makes background indexing take forever. Introduce a new ThreadPriority "Low" that sits in the middle between Background and Default, and maps to QoS class "Utility" on Mac. Make this new priority the default for indexing. This makes the thread run on all cores, but still lowers priority enough to keep the machine responsive, and not interfere with user-initiated actions. I didn't change the implementations for Windows and Linux; on these systems, both ThreadPriority::Background and ThreadPriority::Low map to the same thread priority. This could be changed as a followup (e.g. by using SCHED_BATCH for Low on Linux). See also https://github.com/clangd/clangd/issues/1119. Reviewed By: sammccall, dgoldman Differential Revision: https://reviews.llvm.org/D124715
This commit is contained in:
parent
5bc469fd96
commit
9902a0945d
|
@ -72,7 +72,7 @@ public:
|
|||
explicit Task(std::function<void()> Run) : Run(std::move(Run)) {}
|
||||
|
||||
std::function<void()> Run;
|
||||
llvm::ThreadPriority ThreadPri = llvm::ThreadPriority::Background;
|
||||
llvm::ThreadPriority ThreadPri = llvm::ThreadPriority::Low;
|
||||
unsigned QueuePri = 0; // Higher-priority tasks will run first.
|
||||
std::string Tag; // Allows priority to be boosted later.
|
||||
uint64_t Key = 0; // If the key matches a previous task, drop this one.
|
||||
|
|
|
@ -9025,7 +9025,9 @@ void clang::setThreadBackgroundPriority() {
|
|||
return;
|
||||
|
||||
#if LLVM_ENABLE_THREADS
|
||||
llvm::set_thread_priority(llvm::ThreadPriority::Background);
|
||||
// The function name setThreadBackgroundPriority is for historical reasons;
|
||||
// Low is more appropriate.
|
||||
llvm::set_thread_priority(llvm::ThreadPriority::Low);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -233,15 +233,20 @@ bool llvm_is_multithreaded();
|
|||
unsigned get_cpus();
|
||||
|
||||
enum class ThreadPriority {
|
||||
/// Lower the current thread's priority as much as possible. Can be used
|
||||
/// for long-running tasks that are not time critical; more energy-
|
||||
/// efficient than Low.
|
||||
Background = 0,
|
||||
Default = 1,
|
||||
|
||||
/// Lower the current thread's priority such that it does not affect
|
||||
/// foreground tasks significantly. This is a good default for long-
|
||||
/// running, latency-insensitive tasks to make sure cpu is not hogged
|
||||
/// by this task.
|
||||
Low = 1,
|
||||
|
||||
/// Restore the current thread's priority to default scheduling priority.
|
||||
Default = 2,
|
||||
};
|
||||
/// If priority is Background tries to lower current threads priority such
|
||||
/// that it does not affect foreground tasks significantly. Can be used for
|
||||
/// long-running, latency-insensitive tasks to make sure cpu is not hogged by
|
||||
/// this task.
|
||||
/// If the priority is default tries to restore current threads priority to
|
||||
/// default scheduling priority.
|
||||
enum class SetThreadPriorityResult { FAILURE, SUCCESS };
|
||||
SetThreadPriorityResult set_thread_priority(ThreadPriority Priority);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#if defined(__APPLE__)
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/mach_port.h>
|
||||
#include <pthread/qos.h>
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
@ -258,27 +259,29 @@ SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) {
|
|||
// SCHED_OTHER the standard round-robin time-sharing policy;
|
||||
return !pthread_setschedparam(
|
||||
pthread_self(),
|
||||
Priority == ThreadPriority::Background ? SCHED_IDLE : SCHED_OTHER,
|
||||
// FIXME: consider SCHED_BATCH for Low
|
||||
Priority == ThreadPriority::Default ? SCHED_OTHER : SCHED_IDLE,
|
||||
&priority)
|
||||
? SetThreadPriorityResult::SUCCESS
|
||||
: SetThreadPriorityResult::FAILURE;
|
||||
#elif defined(__APPLE__)
|
||||
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpriority.2.html
|
||||
// When setting a thread into background state the scheduling priority is set
|
||||
// to lowest value, disk and network IO are throttled. Network IO will be
|
||||
// throttled for any sockets the thread opens after going into background
|
||||
// state. Any previously opened sockets are not affected.
|
||||
|
||||
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/getiopolicy_np.3.html
|
||||
// I/Os with THROTTLE policy are called THROTTLE I/Os. If a THROTTLE I/O
|
||||
// request occurs within a small time window (usually a fraction of a second)
|
||||
// of another NORMAL I/O request, the thread that issues the THROTTLE I/O is
|
||||
// forced to sleep for a certain interval. This slows down the thread that
|
||||
// issues the THROTTLE I/O so that NORMAL I/Os can utilize most of the disk
|
||||
// I/O bandwidth.
|
||||
return !setpriority(PRIO_DARWIN_THREAD, 0,
|
||||
Priority == ThreadPriority::Background ? PRIO_DARWIN_BG
|
||||
: 0)
|
||||
// https://developer.apple.com/documentation/apple-silicon/tuning-your-code-s-performance-for-apple-silicon
|
||||
//
|
||||
// Background - Applies to work that isn’t visible to the user and may take significant
|
||||
// time to complete. Examples include indexing, backing up, or synchronizing data. This
|
||||
// class emphasizes energy efficiency.
|
||||
//
|
||||
// Utility - Applies to work that takes anywhere from a few seconds to a few minutes to
|
||||
// complete. Examples include downloading a document or importing data. This class
|
||||
// offers a balance between responsiveness, performance, and energy efficiency.
|
||||
const auto qosClass = [&](){
|
||||
switch (Priority) {
|
||||
case ThreadPriority::Background: return QOS_CLASS_BACKGROUND;
|
||||
case ThreadPriority::Low: return QOS_CLASS_UTILITY;
|
||||
case ThreadPriority::Default: return QOS_CLASS_DEFAULT;
|
||||
}
|
||||
}();
|
||||
return !pthread_set_qos_class_self_np(qosClass, 0)
|
||||
? SetThreadPriorityResult::SUCCESS
|
||||
: SetThreadPriorityResult::FAILURE;
|
||||
#endif
|
||||
|
|
|
@ -120,8 +120,10 @@ SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) {
|
|||
// End background processing mode. The system restores the resource scheduling
|
||||
// priorities of the thread as they were before the thread entered background
|
||||
// processing mode.
|
||||
//
|
||||
// FIXME: consider THREAD_PRIORITY_BELOW_NORMAL for Low
|
||||
return SetThreadPriority(GetCurrentThread(),
|
||||
Priority == ThreadPriority::Background
|
||||
Priority != ThreadPriority::Default
|
||||
? THREAD_MODE_BACKGROUND_BEGIN
|
||||
: THREAD_MODE_BACKGROUND_END)
|
||||
? SetThreadPriorityResult::SUCCESS
|
||||
|
|
Loading…
Reference in New Issue