47
47
48
48
use std:: cmp:: Ordering ;
49
49
use std:: collections:: { HashSet , HashMap , BinaryHeap , BTreeMap } ;
50
- use std:: iter:: FromIterator ;
51
50
use std:: fmt;
51
+ use std:: iter:: FromIterator ;
52
52
use std:: ops:: Range ;
53
53
use std:: rc:: Rc ;
54
+ use std:: time:: { Instant , Duration } ;
54
55
55
56
use semver;
56
57
use url:: Url ;
@@ -362,7 +363,8 @@ type Activations = HashMap<String, HashMap<SourceId, Vec<Summary>>>;
362
363
pub fn resolve ( summaries : & [ ( Summary , Method ) ] ,
363
364
replacements : & [ ( PackageIdSpec , Dependency ) ] ,
364
365
registry : & mut Registry ,
365
- config : Option < & Config > ) -> CargoResult < Resolve > {
366
+ config : Option < & Config > ,
367
+ print_warnings : bool ) -> CargoResult < Resolve > {
366
368
let cx = Context {
367
369
resolve_graph : RcList :: new ( ) ,
368
370
resolve_features : HashMap :: new ( ) ,
@@ -372,7 +374,7 @@ pub fn resolve(summaries: &[(Summary, Method)],
372
374
warnings : RcList :: new ( ) ,
373
375
} ;
374
376
let _p = profile:: start ( "resolving" ) ;
375
- let cx = activate_deps_loop ( cx, registry, summaries) ?;
377
+ let cx = activate_deps_loop ( cx, registry, summaries, config ) ?;
376
378
377
379
let mut resolve = Resolve {
378
380
graph : cx. graph ( ) ,
@@ -398,11 +400,13 @@ pub fn resolve(summaries: &[(Summary, Method)],
398
400
399
401
// If we have a shell, emit warnings about required deps used as feature.
400
402
if let Some ( config) = config {
401
- let mut shell = config. shell ( ) ;
402
- let mut warnings = & cx. warnings ;
403
- while let Some ( ref head) = warnings. head {
404
- shell. warn ( & head. 0 ) ?;
405
- warnings = & head. 1 ;
403
+ if print_warnings {
404
+ let mut shell = config. shell ( ) ;
405
+ let mut warnings = & cx. warnings ;
406
+ while let Some ( ref head) = warnings. head {
407
+ shell. warn ( & head. 0 ) ?;
408
+ warnings = & head. 1 ;
409
+ }
406
410
}
407
411
}
408
412
@@ -420,7 +424,7 @@ fn activate(cx: &mut Context,
420
424
parent : Option < & Summary > ,
421
425
candidate : Candidate ,
422
426
method : & Method )
423
- -> CargoResult < Option < DepsFrame > > {
427
+ -> CargoResult < Option < ( DepsFrame , Duration ) > > {
424
428
if let Some ( parent) = parent {
425
429
cx. resolve_graph . push ( GraphNode :: Link ( parent. package_id ( ) . clone ( ) ,
426
430
candidate. summary . package_id ( ) . clone ( ) ) ) ;
@@ -448,12 +452,13 @@ fn activate(cx: &mut Context,
448
452
}
449
453
} ;
450
454
455
+ let now = Instant :: now ( ) ;
451
456
let deps = cx. build_deps ( registry, & candidate, method) ?;
452
-
453
- Ok ( Some ( DepsFrame {
457
+ let frame = DepsFrame {
454
458
parent : candidate,
455
459
remaining_siblings : RcVecIter :: new ( Rc :: new ( deps) ) ,
456
- } ) )
460
+ } ;
461
+ Ok ( Some ( ( frame, now. elapsed ( ) ) ) )
457
462
}
458
463
459
464
struct RcVecIter < T > {
@@ -580,7 +585,8 @@ impl RemainingCandidates {
580
585
/// dependency graph, cx.resolve is returned.
581
586
fn activate_deps_loop < ' a > ( mut cx : Context < ' a > ,
582
587
registry : & mut Registry ,
583
- summaries : & [ ( Summary , Method ) ] )
588
+ summaries : & [ ( Summary , Method ) ] ,
589
+ config : Option < & Config > )
584
590
-> CargoResult < Context < ' a > > {
585
591
// Note that a `BinaryHeap` is used for the remaining dependencies that need
586
592
// activation. This heap is sorted such that the "largest value" is the most
@@ -594,10 +600,18 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
594
600
for & ( ref summary, ref method) in summaries {
595
601
debug ! ( "initial activation: {}" , summary. package_id( ) ) ;
596
602
let candidate = Candidate { summary : summary. clone ( ) , replace : None } ;
597
- remaining_deps. extend ( activate ( & mut cx, registry, None , candidate,
598
- method) ?) ;
603
+ let res = activate ( & mut cx, registry, None , candidate, method) ?;
604
+ if let Some ( ( frame, _) ) = res {
605
+ remaining_deps. push ( frame) ;
606
+ }
599
607
}
600
608
609
+ let mut ticks = 0 ;
610
+ let start = Instant :: now ( ) ;
611
+ let time_to_print = Duration :: from_millis ( 500 ) ;
612
+ let mut printed = false ;
613
+ let mut deps_time = Duration :: new ( 0 , 0 ) ;
614
+
601
615
// Main resolution loop, this is the workhorse of the resolution algorithm.
602
616
//
603
617
// You'll note that a few stacks are maintained on the side, which might
@@ -612,6 +626,28 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
612
626
// backtracking states where if we hit an error we can return to in order to
613
627
// attempt to continue resolving.
614
628
while let Some ( mut deps_frame) = remaining_deps. pop ( ) {
629
+
630
+ // If we spend a lot of time here (we shouldn't in most cases) then give
631
+ // a bit of a visual indicator as to what we're doing. Only enable this
632
+ // when stderr is a tty (a human is likely to be watching) to ensure we
633
+ // get deterministic output otherwise when observed by tools.
634
+ //
635
+ // Also note that we hit this loop a lot, so it's fairly performance
636
+ // sensitive. As a result try to defer a possibly expensive operation
637
+ // like `Instant::now` by only checking every N iterations of this loop
638
+ // to amortize the cost of the current time lookup.
639
+ ticks += 1 ;
640
+ if let Some ( config) = config {
641
+ if config. shell ( ) . is_err_tty ( ) &&
642
+ !printed &&
643
+ ticks % 1000 == 0 &&
644
+ start. elapsed ( ) - deps_time > time_to_print
645
+ {
646
+ printed = true ;
647
+ config. shell ( ) . status ( "Resolving" , "dependency graph..." ) ?;
648
+ }
649
+ }
650
+
615
651
let frame = match deps_frame. remaining_siblings . next ( ) {
616
652
Some ( sibling) => {
617
653
let parent = Summary :: clone ( & deps_frame. parent ) ;
@@ -695,8 +731,11 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
695
731
} ;
696
732
trace ! ( "{}[{}]>{} trying {}" , parent. name( ) , cur, dep. name( ) ,
697
733
candidate. summary. version( ) ) ;
698
- remaining_deps. extend ( activate ( & mut cx, registry, Some ( & parent) ,
699
- candidate, & method) ?) ;
734
+ let res = activate ( & mut cx, registry, Some ( & parent) , candidate, & method) ?;
735
+ if let Some ( ( frame, dur) ) = res {
736
+ remaining_deps. push ( frame) ;
737
+ deps_time += dur;
738
+ }
700
739
}
701
740
702
741
Ok ( cx)
0 commit comments