@@ -37,6 +37,7 @@ pub fn parallel_prime_caches(
3737 BeginCrateDefMap { crate_id : Crate , crate_name : Symbol } ,
3838 EndCrateDefMap { crate_id : Crate } ,
3939 EndCrateImportMap ,
40+ EndSema ,
4041 EndModuleSymbols ,
4142 Cancelled ( Cancelled ) ,
4243 }
@@ -70,84 +71,113 @@ pub fn parallel_prime_caches(
7071 ( reverse_deps, to_be_done_deps)
7172 } ;
7273
73- let ( def_map_work_sender, import_map_work_sender, symbols_work_sender, progress_receiver) = {
74+ let (
75+ def_map_work_sender,
76+ import_map_work_sender,
77+ symbols_work_sender,
78+ sema_work_sender,
79+ progress_receiver,
80+ ) = {
7481 let ( progress_sender, progress_receiver) = crossbeam_channel:: unbounded ( ) ;
7582 let ( def_map_work_sender, def_map_work_receiver) = crossbeam_channel:: unbounded ( ) ;
7683 let ( import_map_work_sender, import_map_work_receiver) = crossbeam_channel:: unbounded ( ) ;
84+ let ( sema_work_sender, sema_work_receiver) = crossbeam_channel:: unbounded ( ) ;
7785 let ( symbols_work_sender, symbols_work_receiver) = crossbeam_channel:: unbounded ( ) ;
78- let prime_caches_worker =
79- move |db : RootDatabase | {
80- let handle_def_map = |crate_id, crate_name| {
81- progress_sender. send ( ParallelPrimeCacheWorkerProgress :: BeginCrateDefMap {
82- crate_id,
83- crate_name,
84- } ) ?;
85-
86- let cancelled = Cancelled :: catch ( || {
87- _ = hir:: crate_def_map ( & db, crate_id) ;
86+ let prime_caches_worker = move |db : RootDatabase | {
87+ let handle_def_map = |crate_id, crate_name| {
88+ progress_sender. send ( ParallelPrimeCacheWorkerProgress :: BeginCrateDefMap {
89+ crate_id,
90+ crate_name,
91+ } ) ?;
92+
93+ let cancelled = Cancelled :: catch ( || {
94+ _ = hir:: crate_def_map ( & db, crate_id) ;
95+ } ) ;
96+
97+ match cancelled {
98+ Ok ( ( ) ) => progress_sender
99+ . send ( ParallelPrimeCacheWorkerProgress :: EndCrateDefMap { crate_id } ) ?,
100+ Err ( cancelled) => progress_sender
101+ . send ( ParallelPrimeCacheWorkerProgress :: Cancelled ( cancelled) ) ?,
102+ }
103+
104+ Ok :: < _ , crossbeam_channel:: SendError < _ > > ( ( ) )
105+ } ;
106+ let handle_sema = |crate_id| {
107+ let cancelled = Cancelled :: catch ( || {
108+ hir:: attach_db ( & db, || {
109+ // method resolution is likely to hit all trait impls at some point
110+ // we pre-populate it here as this will hit a lot of parses ...
111+ _ = hir:: TraitImpls :: for_crate ( & db, crate_id) ;
88112 // we compute the lang items here as the work for them is also highly recursive and will be trigger by the module symbols query
89113 // slowing down leaf crate analysis tremendously as we go back to being blocked on a single thread
90114 _ = hir:: crate_lang_items ( & db, crate_id) ;
91- } ) ;
92-
93- match cancelled {
94- Ok ( ( ) ) => progress_sender
95- . send ( ParallelPrimeCacheWorkerProgress :: EndCrateDefMap { crate_id } ) ?,
96- Err ( cancelled) => progress_sender
97- . send ( ParallelPrimeCacheWorkerProgress :: Cancelled ( cancelled) ) ?,
98- }
115+ } )
116+ } ) ;
99117
100- Ok :: < _ , crossbeam_channel:: SendError < _ > > ( ( ) )
101- } ;
102- let handle_import_map = |crate_id| {
103- let cancelled = Cancelled :: catch ( || _ = db. import_map ( crate_id) ) ;
118+ match cancelled {
119+ Ok ( ( ) ) => progress_sender. send ( ParallelPrimeCacheWorkerProgress :: EndSema ) ?,
120+ Err ( cancelled) => progress_sender
121+ . send ( ParallelPrimeCacheWorkerProgress :: Cancelled ( cancelled) ) ?,
122+ }
104123
105- match cancelled {
106- Ok ( ( ) ) => progress_sender
107- . send ( ParallelPrimeCacheWorkerProgress :: EndCrateImportMap ) ?,
108- Err ( cancelled) => progress_sender
109- . send ( ParallelPrimeCacheWorkerProgress :: Cancelled ( cancelled) ) ?,
110- }
124+ Ok :: < _ , crossbeam_channel:: SendError < _ > > ( ( ) )
125+ } ;
126+ let handle_import_map = |crate_id| {
127+ let cancelled = Cancelled :: catch ( || _ = db. import_map ( crate_id) ) ;
111128
112- Ok :: < _ , crossbeam_channel:: SendError < _ > > ( ( ) )
113- } ;
114- let handle_symbols = |module| {
115- let cancelled = Cancelled :: catch ( AssertUnwindSafe ( || {
116- _ = SymbolIndex :: module_symbols ( & db, module)
117- } ) ) ;
118-
119- match cancelled {
120- Ok ( ( ) ) => progress_sender
121- . send ( ParallelPrimeCacheWorkerProgress :: EndModuleSymbols ) ?,
122- Err ( cancelled) => progress_sender
123- . send ( ParallelPrimeCacheWorkerProgress :: Cancelled ( cancelled) ) ?,
129+ match cancelled {
130+ Ok ( ( ) ) => {
131+ progress_sender. send ( ParallelPrimeCacheWorkerProgress :: EndCrateImportMap ) ?
124132 }
133+ Err ( cancelled) => progress_sender
134+ . send ( ParallelPrimeCacheWorkerProgress :: Cancelled ( cancelled) ) ?,
135+ }
125136
126- Ok :: < _ , crossbeam_channel:: SendError < _ > > ( ( ) )
127- } ;
128-
129- loop {
130- db. unwind_if_revision_cancelled ( ) ;
131-
132- // Biased because we want to prefer def maps.
133- crossbeam_channel:: select_biased! {
134- recv( def_map_work_receiver) -> work => {
135- let Ok ( ( crate_id, crate_name) ) = work else { break } ;
136- handle_def_map( crate_id, crate_name) ?;
137- }
138- recv( import_map_work_receiver) -> work => {
139- let Ok ( crate_id) = work else { break } ;
140- handle_import_map( crate_id) ?;
141- }
142- recv( symbols_work_receiver) -> work => {
143- let Ok ( module) = work else { break } ;
144- handle_symbols( module) ?;
145- }
137+ Ok :: < _ , crossbeam_channel:: SendError < _ > > ( ( ) )
138+ } ;
139+ let handle_symbols = |module : hir:: Module | {
140+ let cancelled = Cancelled :: catch ( AssertUnwindSafe ( || {
141+ _ = SymbolIndex :: module_symbols ( & db, module)
142+ } ) ) ;
143+
144+ match cancelled {
145+ Ok ( ( ) ) => {
146+ progress_sender. send ( ParallelPrimeCacheWorkerProgress :: EndModuleSymbols ) ?
146147 }
148+ Err ( cancelled) => progress_sender
149+ . send ( ParallelPrimeCacheWorkerProgress :: Cancelled ( cancelled) ) ?,
147150 }
151+
148152 Ok :: < _ , crossbeam_channel:: SendError < _ > > ( ( ) )
149153 } ;
150154
155+ loop {
156+ db. unwind_if_revision_cancelled ( ) ;
157+
158+ // Biased because we want to prefer def maps.
159+ crossbeam_channel:: select_biased! {
160+ recv( def_map_work_receiver) -> work => {
161+ let Ok ( ( crate_id, crate_name) ) = work else { break } ;
162+ handle_def_map( crate_id, crate_name) ?;
163+ }
164+ recv( sema_work_receiver) -> work => {
165+ let Ok ( crate_id) = work else { break } ;
166+ handle_sema( crate_id) ?;
167+ }
168+ recv( import_map_work_receiver) -> work => {
169+ let Ok ( crate_id) = work else { break } ;
170+ handle_import_map( crate_id) ?;
171+ }
172+ recv( symbols_work_receiver) -> work => {
173+ let Ok ( module) = work else { break } ;
174+ handle_symbols( module) ?;
175+ }
176+ }
177+ }
178+ Ok :: < _ , crossbeam_channel:: SendError < _ > > ( ( ) )
179+ } ;
180+
151181 for id in 0 ..num_worker_threads {
152182 stdx:: thread:: Builder :: new (
153183 stdx:: thread:: ThreadIntent :: Worker ,
@@ -162,13 +192,20 @@ pub fn parallel_prime_caches(
162192 . expect ( "failed to spawn thread" ) ;
163193 }
164194
165- ( def_map_work_sender, import_map_work_sender, symbols_work_sender, progress_receiver)
195+ (
196+ def_map_work_sender,
197+ import_map_work_sender,
198+ symbols_work_sender,
199+ sema_work_sender,
200+ progress_receiver,
201+ )
166202 } ;
167203
168204 let crate_def_maps_total = db. all_crates ( ) . len ( ) ;
169205 let mut crate_def_maps_done = 0 ;
170206 let ( mut crate_import_maps_total, mut crate_import_maps_done) = ( 0usize , 0usize ) ;
171207 let ( mut module_symbols_total, mut module_symbols_done) = ( 0usize , 0usize ) ;
208+ let ( mut sema_total, mut sema_done) = ( 0usize , 0usize ) ;
172209
173210 // an index map is used to preserve ordering so we can sort the progress report in order of
174211 // "longest crate to index" first
@@ -187,6 +224,7 @@ pub fn parallel_prime_caches(
187224 while crate_def_maps_done < crate_def_maps_total
188225 || crate_import_maps_done < crate_import_maps_total
189226 || module_symbols_done < module_symbols_total
227+ || sema_done < sema_total
190228 {
191229 db. unwind_if_revision_cancelled ( ) ;
192230
@@ -233,6 +271,7 @@ pub fn parallel_prime_caches(
233271 }
234272
235273 if crate_def_maps_done == crate_def_maps_total {
274+ // Can we trigger lru-eviction once at this point to reduce peak memory usage?
236275 cb ( ParallelPrimeCachesProgress {
237276 crates_currently_indexing : vec ! [ ] ,
238277 crates_done : crate_def_maps_done,
@@ -241,6 +280,8 @@ pub fn parallel_prime_caches(
241280 } ) ;
242281 }
243282
283+ sema_work_sender. send ( crate_id) . ok ( ) ;
284+ sema_total += 1 ;
244285 let origin = & crate_id. data ( db) . origin ;
245286 if origin. is_lang ( ) {
246287 crate_import_maps_total += 1 ;
@@ -264,6 +305,7 @@ pub fn parallel_prime_caches(
264305 }
265306 ParallelPrimeCacheWorkerProgress :: EndCrateImportMap => crate_import_maps_done += 1 ,
266307 ParallelPrimeCacheWorkerProgress :: EndModuleSymbols => module_symbols_done += 1 ,
308+ ParallelPrimeCacheWorkerProgress :: EndSema => sema_done += 1 ,
267309 ParallelPrimeCacheWorkerProgress :: Cancelled ( cancelled) => {
268310 // Cancelled::throw should probably be public
269311 std:: panic:: resume_unwind ( Box :: new ( cancelled) ) ;
0 commit comments