Merge #2906
2906: Fix thread priority problems on windows r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
d1330a4a65
4 changed files with 27 additions and 6 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1079,6 +1079,7 @@ dependencies = [
|
||||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"test_utils 0.1.0",
|
"test_utils 0.1.0",
|
||||||
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
status = [
|
status = [
|
||||||
"Rust (ubuntu-latest)",
|
"Rust (ubuntu-latest)",
|
||||||
# "Rust (windows-latest)",
|
"Rust (windows-latest)",
|
||||||
"Rust (macos-latest)",
|
"Rust (macos-latest)",
|
||||||
"TypeScript"
|
"TypeScript"
|
||||||
]
|
]
|
||||||
|
|
|
@ -30,6 +30,9 @@ env_logger = { version = "0.7.1", default-features = false }
|
||||||
ra_cargo_watch = { path = "../ra_cargo_watch" }
|
ra_cargo_watch = { path = "../ra_cargo_watch" }
|
||||||
either = "1.5"
|
either = "1.5"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
winapi = "0.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
test_utils = { path = "../test_utils" }
|
test_utils = { path = "../test_utils" }
|
||||||
|
|
|
@ -29,9 +29,6 @@ use crate::{
|
||||||
Result, ServerConfig,
|
Result, ServerConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
const THREADPOOL_SIZE: usize = 8;
|
|
||||||
const MAX_IN_FLIGHT_LIBS: usize = THREADPOOL_SIZE - 3;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LspError {
|
pub struct LspError {
|
||||||
pub code: i32,
|
pub code: i32,
|
||||||
|
@ -60,6 +57,25 @@ pub fn main_loop(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
log::info!("server_config: {:#?}", config);
|
log::info!("server_config: {:#?}", config);
|
||||||
|
|
||||||
|
// Windows scheduler implements priority boosts: if thread waits for an
|
||||||
|
// event (like a condvar), and event fires, priority of the thread is
|
||||||
|
// temporary bumped. This optimization backfires in our case: each time the
|
||||||
|
// `main_loop` schedules a task to run on a threadpool, the worker threads
|
||||||
|
// gets a higher priority, and (on a machine with fewer cores) displaces the
|
||||||
|
// main loop! We work-around this by marking the main loop as a
|
||||||
|
// higher-priority thread.
|
||||||
|
//
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/procthread/priority-boosts
|
||||||
|
// https://github.com/rust-analyzer/rust-analyzer/issues/2835
|
||||||
|
#[cfg(windows)]
|
||||||
|
unsafe {
|
||||||
|
use winapi::um::processthreadsapi::*;
|
||||||
|
let thread = GetCurrentThread();
|
||||||
|
let thread_priority_above_normal = 1;
|
||||||
|
SetThreadPriority(thread, thread_priority_above_normal);
|
||||||
|
}
|
||||||
|
|
||||||
let mut loop_state = LoopState::default();
|
let mut loop_state = LoopState::default();
|
||||||
let mut world_state = {
|
let mut world_state = {
|
||||||
let feature_flags = {
|
let feature_flags = {
|
||||||
|
@ -168,7 +184,7 @@ pub fn main_loop(
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let pool = ThreadPool::new(THREADPOOL_SIZE);
|
let pool = ThreadPool::default();
|
||||||
let (task_sender, task_receiver) = unbounded::<Task>();
|
let (task_sender, task_receiver) = unbounded::<Task>();
|
||||||
let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>();
|
let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>();
|
||||||
|
|
||||||
|
@ -371,7 +387,8 @@ fn loop_turn(
|
||||||
loop_state.pending_libraries.extend(changes);
|
loop_state.pending_libraries.extend(changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
while loop_state.in_flight_libraries < MAX_IN_FLIGHT_LIBS
|
let max_in_flight_libs = pool.max_count().saturating_sub(2).max(1);
|
||||||
|
while loop_state.in_flight_libraries < max_in_flight_libs
|
||||||
&& !loop_state.pending_libraries.is_empty()
|
&& !loop_state.pending_libraries.is_empty()
|
||||||
{
|
{
|
||||||
let (root, files) = loop_state.pending_libraries.pop().unwrap();
|
let (root, files) = loop_state.pending_libraries.pop().unwrap();
|
||||||
|
|
Loading…
Add table
Reference in a new issue