From f9ce939bf53b84f7e6e4ecca3875dd0c378991db Mon Sep 17 00:00:00 2001 From: Luna Razzaghipour Date: Wed, 3 Sep 2025 11:34:46 +1000 Subject: [PATCH] perf: scheduler priority clamping on macOS #35488 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: All of Nvim’s threads are clamped to the Default QoS class. This means that Nvim is forced to compete for CPU time with compilers and other batch work, and is even prioritized beneath user-initiated work in GUI apps like e.g. file imports. This significantly harms responsiveness. Solution: Tell the kernel that the Nvim process takes part in rendering a UI. Implementation: Remove the process-wide QoS clamp. This doesn’t directly do anything to the main thread, but rather has the side-effect of letting the main thread run at its actual QoS (User Interactive QoS). --- src/nvim/main.c | 1 + src/nvim/os/env.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/nvim/main.c b/src/nvim/main.c index 3bed6964ac..336dea4e6e 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -188,6 +188,7 @@ static bool event_teardown(void) /// Needed for unit tests. void early_init(mparm_T *paramp) { + os_hint_priority(); estack_init(); cmdline_init(); eval_init(); // init global variables diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 49ca5fab82..8d4a86537f 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -39,6 +39,10 @@ # include "nvim/fileio.h" #endif +#ifdef __APPLE__ +# include +#endif + #ifdef HAVE__NSGETENVIRON # include #endif @@ -367,6 +371,18 @@ int64_t os_get_pid(void) #endif } +/// Signals to the OS that Nvim is an application for "interactive work" +/// which should be prioritized similar to a GUI app. +void os_hint_priority(void) +{ +#ifdef __APPLE__ + // By default, processes have the TASK_UNSPECIFIED "role", which means all of its threads are + // clamped to Default QoS. Setting the role to TASK_DEFAULT_APPLICATION removes this clamp. + integer_t policy = TASK_DEFAULT_APPLICATION; + task_policy_set(mach_task_self(), TASK_CATEGORY_POLICY, &policy, 1); +#endif +} + /// Gets the hostname of the current machine. /// /// @param hostname Buffer to store the hostname.