@@ -77,8 +77,8 @@ bool DryRunCommandRunner::WaitForCommand(Result* result) {
77
77
78
78
79
79
bool EdgeQueue::EdgePriorityCompare::operator ()(const Edge* e1 , const Edge* e2 ) const {
80
- const uint64_t ct1 = e1 ->critical_time ();
81
- const uint64_t ct2 = e2 ->critical_time ();
80
+ const int64_t ct1 = e1 ->critical_time ();
81
+ const int64_t ct2 = e2 ->critical_time ();
82
82
if (ct1 != ct2) {
83
83
return ct1 < ct2;
84
84
}
@@ -464,28 +464,10 @@ void Plan::ComputeCriticalTime(BuildLog* build_log) {
464
464
targets_.end ());
465
465
}
466
466
467
-
468
- std::vector<Edge*> edges;
469
- std::map<Node*, int > num_out_edges;
470
- for (std::map<Edge*, Want>::iterator it = want_.begin (), end = want_.end ();
471
- it != end; ++it) {
472
- if (it->second != kWantNothing )
473
- continue ;
474
- Edge* e = it->first ;
475
- edges.push_back (e);
476
- std::set<Node*> ins; // protect against #308; also sanity
477
- for (size_t nit = 0 ; nit < e->inputs_ .size (); ++nit) {
478
- Node* n = e->inputs_ [nit];
479
- if (ins.insert (n).second ) {
480
- num_out_edges[n]++;
481
- }
482
- }
483
- }
484
-
485
467
// this is total time if building all edges in serial, so this value is big
486
468
// enough to ensure higher priority target initial critical time always bigger
487
469
// than lower one
488
- uint64_t total_time = 0 ;
470
+ int64_t total_time = 0 ;
489
471
// Critical path scheduling.
490
472
// 0. Assign costs to all edges, using:
491
473
// a) The time the edge needed last time, if available.
@@ -496,11 +478,12 @@ void Plan::ComputeCriticalTime(BuildLog* build_log) {
496
478
// c) A fixed cost if this type of edge hasn't run before (0 for phony target,
497
479
// 1 for others)
498
480
//
499
- for (std::vector <Edge*>::iterator it = edges .begin (), end = edges .end (); it != end ;
500
- total_time += (*it)-> run_time_ms_ , ++it) {
501
- Edge* edge = *it ;
502
- if (edge->is_phony ())
481
+ for (std::map <Edge*, Want >::iterator it = want_ .begin (), end = want_ .end ();
482
+ it != end; ++it) {
483
+ Edge* edge = it-> first ;
484
+ if (edge->is_phony ()) {
503
485
continue ;
486
+ }
504
487
BuildLog::LogEntry* entry =
505
488
build_log->LookupByOutput (edge->outputs_ [0 ]->path ());
506
489
if (!entry) {
@@ -512,63 +495,47 @@ void Plan::ComputeCriticalTime(BuildLog* build_log) {
512
495
}
513
496
514
497
// Use backflow algorithm to compute critical times for all nodes, starting
515
- // from the destination nodes. use priority_weight = total_time * N as
516
- // initial critical time to makes forward edgs of higher priority always
517
- // get higher critical time value
498
+ // from the destination nodes.
518
499
// XXX: ignores pools
519
- std::queue<Edge*> edgesQ;
520
-
521
- // Makes sure that each edge is added to the queue just once. This is needed
522
- // for example if a binary is used to generate 50 source files, and all the
523
- // source file cxx lines are added. Without this, the edge generating that
524
- // binary would be added ot the queue 50 times.
525
- std::set<Edge*> done;
500
+ std::set<Edge*> active_edges; // All edges in edgesQ (for uniqueness)
501
+ std::queue<Edge*> edgesQ; // Queue, for breadth-first traversal
526
502
527
503
for (std::vector<const Node*>::reverse_iterator it = targets_.rbegin (),
528
504
end = targets_.rend ();
529
505
it != end; ++it) {
530
506
if (Edge* in = (*it)->in_edge ()) {
531
- uint64_t priority_weight = (it - targets_.rbegin ()) * total_time;
507
+ // Use initial critical time: total_time * N. This means higher
508
+ // priority targets always get a higher critical time value
509
+ int64_t priority_weight = (it - targets_.rbegin ()) * total_time;
532
510
in->set_critical_time (
533
- std::max (std::max< uint64_t >(in-> run_time_ms_ , priority_weight),
534
- in->critical_time ()));
535
- if (done .insert (in).second ) {
511
+ priority_weight +
512
+ std::max< int64_t >(in-> run_time_ms_ , in->critical_time ()));
513
+ if (active_edges .insert (in).second ) {
536
514
edgesQ.push (in);
515
+ all_edges.insert (in);
537
516
}
538
517
}
539
518
}
519
+
540
520
while (!edgesQ.empty ()) {
541
- Edge* e = edgesQ.front (); edgesQ.pop ();
542
- bool all_nodes_ready = true ;
543
- uint64_t max_crit = 0 ;
544
- for (std::vector<Node*>::iterator it = e->outputs_ .begin (),
545
- end = e->outputs_ .end ();
546
- it != end; ++it) {
547
- if (num_out_edges[*it] > 0 ) {
548
- all_nodes_ready = false ;
549
- continue ;
550
- }
551
- for (std::vector<Edge*>::const_iterator eit = (*it)->out_edges ().begin (),
552
- eend = (*it)->out_edges ().end ();
553
- eit != eend; ++eit) {
554
- max_crit = std::max ((*eit)->critical_time (), max_crit);
555
- }
556
- }
557
- if (!all_nodes_ready) {
558
- // To the back it goes.
559
- // XXX: think about how often this can happen.
560
- edgesQ.push (e);
561
- continue ;
562
- }
563
- e->set_critical_time (std::max (max_crit + e->run_time_ms_ , e->critical_time ()));
521
+ Edge* e = edgesQ.front ();
522
+ edgesQ.pop ();
523
+ active_edges.erase (e);
564
524
565
525
for (std::vector<Node*>::iterator it = e->inputs_ .begin (),
566
526
end = e->inputs_ .end ();
567
527
it != end; ++it) {
568
- num_out_edges[*it]--;
569
- if (Edge* in = (*it)->in_edge ()) {
570
- if (done.insert (in).second ) {
528
+ Edge* in = (*it)->in_edge ();
529
+ if (!in) {
530
+ continue ;
531
+ }
532
+ // Only process edge if this node offers a higher critical time
533
+ const int64_t proposed_time = e->critical_time () + in->run_time_ms_ ;
534
+ if (proposed_time > in->critical_time ()) {
535
+ in->set_critical_time (proposed_time);
536
+ if (active_edges.insert (in).second ) {
571
537
edgesQ.push (in);
538
+ all_edges.insert (in);
572
539
}
573
540
}
574
541
}
@@ -725,7 +692,7 @@ bool Builder::AlreadyUpToDate() const {
725
692
bool Builder::Build (string* err) {
726
693
assert (!AlreadyUpToDate ());
727
694
728
- plan_.ComputePriorityList (scan_.build_log ());
695
+ plan_.ComputeCriticalTime (scan_.build_log ());
729
696
730
697
status_->PlanHasTotalEdges (plan_.command_edge_count ());
731
698
int pending_commands = 0 ;
0 commit comments