47
47
//! that we're implementing something that probably shouldn't be allocating all
48
48
//! over the place.
49
49
50
- use std:: collections:: { BTreeMap , BinaryHeap , HashMap , HashSet } ;
50
+ use std:: collections:: { BTreeMap , HashMap , HashSet } ;
51
51
use std:: mem;
52
52
use std:: rc:: Rc ;
53
53
use std:: time:: { Duration , Instant } ;
@@ -64,7 +64,7 @@ use util::profile;
64
64
65
65
use self :: context:: { Activations , Context } ;
66
66
use self :: types:: { ActivateError , ActivateResult , Candidate , ConflictReason , DepsFrame , GraphNode } ;
67
- use self :: types:: { RcVecIter , RegistryQueryer } ;
67
+ use self :: types:: { RcVecIter , RegistryQueryer , RemainingDeps , ResolverProgress } ;
68
68
69
69
pub use self :: encode:: { EncodableDependency , EncodablePackageId , EncodableResolve } ;
70
70
pub use self :: encode:: { Metadata , WorkspaceResolve } ;
@@ -170,15 +170,8 @@ fn activate_deps_loop(
170
170
summaries : & [ ( Summary , Method ) ] ,
171
171
config : Option < & Config > ,
172
172
) -> CargoResult < Context > {
173
- // Note that a `BinaryHeap` is used for the remaining dependencies that need
174
- // activation. This heap is sorted such that the "largest value" is the most
175
- // constrained dependency, or the one with the least candidates.
176
- //
177
- // This helps us get through super constrained portions of the dependency
178
- // graph quickly and hopefully lock down what later larger dependencies can
179
- // use (those with more candidates).
180
173
let mut backtrack_stack = Vec :: new ( ) ;
181
- let mut remaining_deps = BinaryHeap :: new ( ) ;
174
+ let mut remaining_deps = RemainingDeps :: new ( ) ;
182
175
183
176
// `past_conflicting_activations` is a cache of the reasons for each time we
184
177
// backtrack.
@@ -200,11 +193,7 @@ fn activate_deps_loop(
200
193
}
201
194
}
202
195
203
- let mut ticks = 0u16 ;
204
- let start = Instant :: now ( ) ;
205
- let time_to_print = Duration :: from_millis ( 500 ) ;
206
- let mut printed = false ;
207
- let mut deps_time = Duration :: new ( 0 , 0 ) ;
196
+ let mut printed = ResolverProgress :: new ( ) ;
208
197
209
198
// Main resolution loop, this is the workhorse of the resolution algorithm.
210
199
//
@@ -219,55 +208,14 @@ fn activate_deps_loop(
219
208
// its own dependencies in turn. The `backtrack_stack` is a side table of
220
209
// backtracking states where if we hit an error we can return to in order to
221
210
// attempt to continue resolving.
222
- while let Some ( mut deps_frame) = remaining_deps. pop ( ) {
223
- // If we spend a lot of time here (we shouldn't in most cases) then give
224
- // a bit of a visual indicator as to what we're doing. Only enable this
225
- // when stderr is a tty (a human is likely to be watching) to ensure we
226
- // get deterministic output otherwise when observed by tools.
227
- //
228
- // Also note that we hit this loop a lot, so it's fairly performance
229
- // sensitive. As a result try to defer a possibly expensive operation
230
- // like `Instant::now` by only checking every N iterations of this loop
231
- // to amortize the cost of the current time lookup.
232
- ticks += 1 ;
233
- if let Some ( config) = config {
234
- if config. shell ( ) . is_err_tty ( )
235
- && !printed
236
- && ticks % 1000 == 0
237
- && start. elapsed ( ) - deps_time > time_to_print
238
- {
239
- printed = true ;
240
- config. shell ( ) . status ( "Resolving" , "dependency graph..." ) ?;
241
- }
242
- }
243
- // The largest test in our sweet takes less then 5000 ticks
244
- // with all the algorithm improvements.
245
- // If any of them are removed then it takes more than I am willing to measure.
246
- // So lets fail the test fast if we have ben running for two long.
247
- debug_assert ! ( ticks < 50_000 ) ;
248
- // The largest test in our sweet takes less then 30 sec
249
- // with all the improvements to how fast a tick can go.
250
- // If any of them are removed then it takes more than I am willing to measure.
251
- // So lets fail the test fast if we have ben running for two long.
252
- if cfg ! ( debug_assertions) && ( ticks % 1000 == 0 ) {
253
- assert ! ( start. elapsed( ) - deps_time < Duration :: from_secs( 90 ) ) ;
254
- }
255
-
256
- let just_here_for_the_error_messages = deps_frame. just_for_error_messages ;
257
-
258
- // Figure out what our next dependency to activate is, and if nothing is
259
- // listed then we're entirely done with this frame (yay!) and we can
260
- // move on to the next frame.
261
- let frame = match deps_frame. remaining_siblings . next ( ) {
262
- Some ( sibling) => {
263
- let parent = Summary :: clone ( & deps_frame. parent ) ;
264
- remaining_deps. push ( deps_frame) ;
265
- ( parent, sibling)
266
- }
267
- None => continue ,
268
- } ;
211
+ while let Some ( ( just_here_for_the_error_messages, frame) ) =
212
+ remaining_deps. pop_most_constrained ( )
213
+ {
269
214
let ( mut parent, ( mut cur, ( mut dep, candidates, mut features) ) ) = frame;
270
- assert ! ( !remaining_deps. is_empty( ) ) ;
215
+
216
+ // If we spend a lot of time here (we shouldn't in most cases) then give
217
+ // a bit of a visual indicator as to what we're doing.
218
+ printed. shell_status ( config) ?;
271
219
272
220
trace ! (
273
221
"{}[{}]>{} {} candidates" ,
@@ -398,7 +346,7 @@ fn activate_deps_loop(
398
346
Some ( BacktrackFrame {
399
347
cur,
400
348
context_backup : Context :: clone ( & cx) ,
401
- deps_backup : < BinaryHeap < DepsFrame > > :: clone ( & remaining_deps ) ,
349
+ deps_backup : remaining_deps . clone ( ) ,
402
350
remaining_candidates : remaining_candidates. clone ( ) ,
403
351
parent : Summary :: clone ( & parent) ,
404
352
dep : Dependency :: clone ( & dep) ,
@@ -431,7 +379,7 @@ fn activate_deps_loop(
431
379
// frame in the end if it looks like it's not going to end well,
432
380
// so figure that out here.
433
381
Ok ( Some ( ( mut frame, dur) ) ) => {
434
- deps_time += dur;
382
+ printed . elapsed ( dur) ;
435
383
436
384
// Our `frame` here is a new package with its own list of
437
385
// dependencies. Do a sanity check here of all those
@@ -486,7 +434,6 @@ fn activate_deps_loop(
486
434
{
487
435
if let Some ( ( other_parent, conflict) ) = remaining_deps
488
436
. iter ( )
489
- . flat_map ( |other| other. flatten ( ) )
490
437
// for deps related to us
491
438
. filter ( |& ( _, ref other_dep) | {
492
439
known_related_bad_deps. contains ( other_dep)
@@ -683,7 +630,7 @@ fn activate(
683
630
struct BacktrackFrame {
684
631
cur : usize ,
685
632
context_backup : Context ,
686
- deps_backup : BinaryHeap < DepsFrame > ,
633
+ deps_backup : RemainingDeps ,
687
634
remaining_candidates : RemainingCandidates ,
688
635
parent : Summary ,
689
636
dep : Dependency ,
0 commit comments