diff options
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r-- | crates/ra_lsp_server/Cargo.toml | 7 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 43 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 5 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/world.rs | 4 |
4 files changed, 39 insertions, 20 deletions
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 579158780..fdf81ed87 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml | |||
@@ -14,7 +14,7 @@ serde_json = "1.0.34" | |||
14 | serde = { version = "1.0.83", features = ["derive"] } | 14 | serde = { version = "1.0.83", features = ["derive"] } |
15 | crossbeam-channel = "0.4" | 15 | crossbeam-channel = "0.4" |
16 | log = "0.4.3" | 16 | log = "0.4.3" |
17 | lsp-types = { version = "0.69.0", features = ["proposed"] } | 17 | lsp-types = { version = "0.70.0", features = ["proposed"] } |
18 | rustc-hash = "1.0" | 18 | rustc-hash = "1.0" |
19 | parking_lot = "0.10.0" | 19 | parking_lot = "0.10.0" |
20 | jod-thread = "0.1.0" | 20 | jod-thread = "0.1.0" |
@@ -26,10 +26,13 @@ lsp-server = "0.3.0" | |||
26 | ra_project_model = { path = "../ra_project_model" } | 26 | ra_project_model = { path = "../ra_project_model" } |
27 | ra_prof = { path = "../ra_prof" } | 27 | ra_prof = { path = "../ra_prof" } |
28 | ra_vfs_glob = { path = "../ra_vfs_glob" } | 28 | ra_vfs_glob = { path = "../ra_vfs_glob" } |
29 | env_logger = { version = "0.7.1", default-features = false, features = ["humantime"] } | 29 | env_logger = { version = "0.7.1", default-features = false } |
30 | ra_cargo_watch = { path = "../ra_cargo_watch" } | 30 | ra_cargo_watch = { path = "../ra_cargo_watch" } |
31 | either = "1.5" | 31 | either = "1.5" |
32 | 32 | ||
33 | [target.'cfg(windows)'.dependencies] | ||
34 | winapi = "0.3" | ||
35 | |||
33 | [dev-dependencies] | 36 | [dev-dependencies] |
34 | tempfile = "3" | 37 | tempfile = "3" |
35 | test_utils = { path = "../test_utils" } | 38 | test_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 7822be2e2..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 | ||
32 | const THREADPOOL_SIZE: usize = 8; | ||
33 | const MAX_IN_FLIGHT_LIBS: usize = THREADPOOL_SIZE - 3; | ||
34 | |||
35 | #[derive(Debug)] | 32 | #[derive(Debug)] |
36 | pub struct LspError { | 33 | pub 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 | ||
@@ -210,7 +226,7 @@ pub fn main_loop( | |||
210 | )?; | 226 | )?; |
211 | } | 227 | } |
212 | } | 228 | } |
213 | 229 | world_state.analysis_host.request_cancellation(); | |
214 | log::info!("waiting for tasks to finish..."); | 230 | log::info!("waiting for tasks to finish..."); |
215 | task_receiver.into_iter().for_each(|task| { | 231 | task_receiver.into_iter().for_each(|task| { |
216 | on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut world_state) | 232 | on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut world_state) |
@@ -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(); |
@@ -586,12 +603,14 @@ fn on_notification( | |||
586 | 603 | ||
587 | fn on_check_task( | 604 | fn on_check_task( |
588 | task: CheckTask, | 605 | task: CheckTask, |
589 | world_state: &WorldState, | 606 | world_state: &mut WorldState, |
590 | task_sender: &Sender<Task>, | 607 | task_sender: &Sender<Task>, |
591 | ) -> Result<()> { | 608 | ) -> Result<()> { |
592 | match task { | 609 | match task { |
593 | CheckTask::ClearDiagnostics => { | 610 | CheckTask::ClearDiagnostics => { |
594 | let cleared_files = world_state.check_watcher.state.write().clear(); | 611 | let state = Arc::get_mut(&mut world_state.check_watcher.state) |
612 | .expect("couldn't get check watcher state as mutable"); | ||
613 | let cleared_files = state.clear(); | ||
595 | 614 | ||
596 | // Send updated diagnostics for each cleared file | 615 | // Send updated diagnostics for each cleared file |
597 | for url in cleared_files { | 616 | for url in cleared_files { |
@@ -600,11 +619,9 @@ fn on_check_task( | |||
600 | } | 619 | } |
601 | 620 | ||
602 | CheckTask::AddDiagnostic(url, diagnostic) => { | 621 | CheckTask::AddDiagnostic(url, diagnostic) => { |
603 | world_state | 622 | let state = Arc::get_mut(&mut world_state.check_watcher.state) |
604 | .check_watcher | 623 | .expect("couldn't get check watcher state as mutable"); |
605 | .state | 624 | state.add_diagnostic_with_fixes(url.clone(), diagnostic); |
606 | .write() | ||
607 | .add_diagnostic_with_fixes(url.clone(), diagnostic); | ||
608 | 625 | ||
609 | // We manually send a diagnostic update when the watcher asks | 626 | // We manually send a diagnostic update when the watcher asks |
610 | // us to, to avoid the issue of having to change the file to | 627 | // us to, to avoid the issue of having to change the file to |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 8e43f0575..666f2ee29 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -674,8 +674,7 @@ pub fn handle_code_action( | |||
674 | res.push(action.into()); | 674 | res.push(action.into()); |
675 | } | 675 | } |
676 | 676 | ||
677 | for fix in world.check_watcher.read().fixes_for(¶ms.text_document.uri).into_iter().flatten() | 677 | for fix in world.check_watcher.fixes_for(¶ms.text_document.uri).into_iter().flatten() { |
678 | { | ||
679 | let fix_range = fix.location.range.conv_with(&line_index); | 678 | let fix_range = fix.location.range.conv_with(&line_index); |
680 | if fix_range.intersection(&range).is_none() { | 679 | if fix_range.intersection(&range).is_none() { |
681 | continue; | 680 | continue; |
@@ -895,7 +894,7 @@ pub fn publish_diagnostics( | |||
895 | tags: None, | 894 | tags: None, |
896 | }) | 895 | }) |
897 | .collect(); | 896 | .collect(); |
898 | if let Some(check_diags) = world.check_watcher.read().diagnostics_for(&uri) { | 897 | if let Some(check_diags) = world.check_watcher.diagnostics_for(&uri) { |
899 | diagnostics.extend(check_diags.iter().cloned()); | 898 | diagnostics.extend(check_diags.iter().cloned()); |
900 | } | 899 | } |
901 | Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None }) | 900 | Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None }) |
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index e7a0acfc7..3059ef9ec 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs | |||
@@ -63,7 +63,7 @@ pub struct WorldSnapshot { | |||
63 | pub workspaces: Arc<Vec<ProjectWorkspace>>, | 63 | pub workspaces: Arc<Vec<ProjectWorkspace>>, |
64 | pub analysis: Analysis, | 64 | pub analysis: Analysis, |
65 | pub latest_requests: Arc<RwLock<LatestRequests>>, | 65 | pub latest_requests: Arc<RwLock<LatestRequests>>, |
66 | pub check_watcher: Arc<RwLock<CheckState>>, | 66 | pub check_watcher: CheckState, |
67 | vfs: Arc<RwLock<Vfs>>, | 67 | vfs: Arc<RwLock<Vfs>>, |
68 | } | 68 | } |
69 | 69 | ||
@@ -220,7 +220,7 @@ impl WorldState { | |||
220 | analysis: self.analysis_host.analysis(), | 220 | analysis: self.analysis_host.analysis(), |
221 | vfs: Arc::clone(&self.vfs), | 221 | vfs: Arc::clone(&self.vfs), |
222 | latest_requests: Arc::clone(&self.latest_requests), | 222 | latest_requests: Arc::clone(&self.latest_requests), |
223 | check_watcher: self.check_watcher.state.clone(), | 223 | check_watcher: (*self.check_watcher.state).clone(), |
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||