@@ -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 ) ]
3633pub 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