aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-01-26 13:17:19 +0000
committerGitHub <[email protected]>2020-01-26 13:17:19 +0000
commitd1330a4a65f0113c687716a5a679239af4df9c11 (patch)
treee32c7483d541e3d38668f44d2ed61a21151dbed8 /crates/ra_lsp_server
parent13743d10734018b1765b26993044cd4f455fff5a (diff)
parent9faebd9d646e54aaec81a36ff08b45389344e23b (diff)
Merge #2906
2906: Fix thread priority problems on windows r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r--crates/ra_lsp_server/Cargo.toml3
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs27
2 files changed, 25 insertions, 5 deletions
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 5df0496dd..fdf81ed87 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -30,6 +30,9 @@ env_logger = { version = "0.7.1", default-features = false }
30ra_cargo_watch = { path = "../ra_cargo_watch" } 30ra_cargo_watch = { path = "../ra_cargo_watch" }
31either = "1.5" 31either = "1.5"
32 32
33[target.'cfg(windows)'.dependencies]
34winapi = "0.3"
35
33[dev-dependencies] 36[dev-dependencies]
34tempfile = "3" 37tempfile = "3"
35test_utils = { path = "../test_utils" } 38test_utils = { path = "../test_utils" }
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 83adf9711..15bf519c9 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -29,9 +29,6 @@ use crate::{
29 Result, ServerConfig, 29 Result, ServerConfig,
30}; 30};
31 31
32const THREADPOOL_SIZE: usize = 8;
33const MAX_IN_FLIGHT_LIBS: usize = THREADPOOL_SIZE - 3;
34
35#[derive(Debug)] 32#[derive(Debug)]
36pub struct LspError { 33pub struct LspError {
37 pub code: i32, 34 pub code: i32,
@@ -60,6 +57,25 @@ pub fn main_loop(
60) -> Result<()> { 57) -> Result<()> {
61 log::info!("server_config: {:#?}", config); 58 log::info!("server_config: {:#?}", config);
62 59
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
63 let mut loop_state = LoopState::default(); 79 let mut loop_state = LoopState::default();
64 let mut world_state = { 80 let mut world_state = {
65 let feature_flags = { 81 let feature_flags = {
@@ -168,7 +184,7 @@ pub fn main_loop(
168 ) 184 )
169 }; 185 };
170 186
171 let pool = ThreadPool::new(THREADPOOL_SIZE); 187 let pool = ThreadPool::default();
172 let (task_sender, task_receiver) = unbounded::<Task>(); 188 let (task_sender, task_receiver) = unbounded::<Task>();
173 let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>(); 189 let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>();
174 190
@@ -371,7 +387,8 @@ fn loop_turn(
371 loop_state.pending_libraries.extend(changes); 387 loop_state.pending_libraries.extend(changes);
372 } 388 }
373 389
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
375 && !loop_state.pending_libraries.is_empty() 392 && !loop_state.pending_libraries.is_empty()
376 { 393 {
377 let (root, files) = loop_state.pending_libraries.pop().unwrap(); 394 let (root, files) = loop_state.pending_libraries.pop().unwrap();