Skip to content

Commit d1330a4

Browse files
bors[bot]matklad
andauthored
Merge #2906
2906: Fix thread priority problems on windows r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 13743d1 + 9faebd9 commit d1330a4

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bors.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
status = [
22
"Rust (ubuntu-latest)",
3-
# "Rust (windows-latest)",
3+
"Rust (windows-latest)",
44
"Rust (macos-latest)",
55
"TypeScript"
66
]

crates/ra_lsp_server/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ env_logger = { version = "0.7.1", default-features = false }
3030
ra_cargo_watch = { path = "../ra_cargo_watch" }
3131
either = "1.5"
3232

33+
[target.'cfg(windows)'.dependencies]
34+
winapi = "0.3"
35+
3336
[dev-dependencies]
3437
tempfile = "3"
3538
test_utils = { path = "../test_utils" }

crates/ra_lsp_server/src/main_loop.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ use crate::{
2929
Result, ServerConfig,
3030
};
3131

32-
const THREADPOOL_SIZE: usize = 8;
33-
const MAX_IN_FLIGHT_LIBS: usize = THREADPOOL_SIZE - 3;
34-
3532
#[derive(Debug)]
3633
pub struct LspError {
3734
pub code: i32,
@@ -60,6 +57,25 @@ pub fn main_loop(
6057
) -> Result<()> {
6158
log::info!("server_config: {:#?}", config);
6259

60+
// Windows scheduler implements priority boosts: if thread waits for an
61+
// event (like a condvar), and event fires, priority of the thread is
62+
// temporary bumped. This optimization backfires in our case: each time the
63+
// `main_loop` schedules a task to run on a threadpool, the worker threads
64+
// gets a higher priority, and (on a machine with fewer cores) displaces the
65+
// main loop! We work-around this by marking the main loop as a
66+
// higher-priority thread.
67+
//
68+
// https://docs.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities
69+
// https://docs.microsoft.com/en-us/windows/win32/procthread/priority-boosts
70+
// https://github.com/rust-analyzer/rust-analyzer/issues/2835
71+
#[cfg(windows)]
72+
unsafe {
73+
use winapi::um::processthreadsapi::*;
74+
let thread = GetCurrentThread();
75+
let thread_priority_above_normal = 1;
76+
SetThreadPriority(thread, thread_priority_above_normal);
77+
}
78+
6379
let mut loop_state = LoopState::default();
6480
let mut world_state = {
6581
let feature_flags = {
@@ -168,7 +184,7 @@ pub fn main_loop(
168184
)
169185
};
170186

171-
let pool = ThreadPool::new(THREADPOOL_SIZE);
187+
let pool = ThreadPool::default();
172188
let (task_sender, task_receiver) = unbounded::<Task>();
173189
let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>();
174190

@@ -371,7 +387,8 @@ fn loop_turn(
371387
loop_state.pending_libraries.extend(changes);
372388
}
373389

374-
while loop_state.in_flight_libraries < MAX_IN_FLIGHT_LIBS
390+
let max_in_flight_libs = pool.max_count().saturating_sub(2).max(1);
391+
while loop_state.in_flight_libraries < max_in_flight_libs
375392
&& !loop_state.pending_libraries.is_empty()
376393
{
377394
let (root, files) = loop_state.pending_libraries.pop().unwrap();

0 commit comments

Comments
 (0)