@@ -532,6 +532,7 @@ type action struct {
532
532
533
533
f func (* builder , * action ) error // the action itself (nil = no-op)
534
534
ignoreFail bool // whether to run f even if dependencies fail
535
+ weight int // estimated execution time (unitless)
535
536
536
537
// Generated files, directories.
537
538
link bool // target is executable, not just package
@@ -789,31 +790,57 @@ func actionList(root *action) []*action {
789
790
return all
790
791
}
791
792
792
- // do runs the action graph rooted at root.
793
- func (b * builder ) do (root * action ) {
794
- // Build list of all actions, assigning depth-first post-order priority.
795
- // The original implementation here was a true queue
796
- // (using a channel) but it had the effect of getting
797
- // distracted by low-level leaf actions to the detriment
798
- // of completing higher-level actions. The order of
799
- // work does not matter much to overall execution time,
800
- // but when running "go test std" it is nice to see each test
801
- // results as soon as possible. The priorities assigned
802
- // ensure that, all else being equal, the execution prefers
803
- // to do what it would have done first in a simple depth-first
804
- // dependency order traversal.
805
- all := actionList (root )
806
- for i , a := range all {
807
- a .priority = i
793
+ func assignPriorities (all []* action ) {
794
+ for _ , a := range all {
795
+ a .weight = 1 // TODO: better weight estimation
796
+ a .priority = - 1
808
797
}
809
798
810
- b .readySema = make (chan bool , len (all ))
799
+ for assigned := 0 ; assigned < len (all ); {
800
+ for _ , a := range all {
801
+ if a .priority != - 1 {
802
+ continue
803
+ }
804
+ assigned ++
805
+ a .priority = 0
806
+ for _ , a1 := range a .triggers {
807
+ if a1 .priority == - 1 {
808
+ assigned --
809
+ a .priority = - 1
810
+ break
811
+ }
812
+ if a .priority < a1 .priority + 1 {
813
+ a .priority = a1 .priority + a .weight
814
+ }
815
+ }
816
+ }
817
+ }
811
818
812
- // Initialize per-action execution state.
819
+ // TODO: DELETE
820
+ // aq := actionQueue(all)
821
+ // sort.Sort(&aq)
822
+ // for _, a := range aq {
823
+ // if a.p != nil {
824
+ // fmt.Println("*** ", a.p.ImportPath, a.priority)
825
+ // } else {
826
+ // fmt.Println("--- ", a.objpkg, a.priority)
827
+ // }
828
+ // }
829
+ }
830
+
831
+ // do runs the action graph rooted at root.
832
+ func (b * builder ) do (root * action ) {
833
+ all := actionList (root )
813
834
for _ , a := range all {
814
835
for _ , a1 := range a .deps {
815
836
a1 .triggers = append (a1 .triggers , a )
816
837
}
838
+ }
839
+ assignPriorities (all )
840
+
841
+ // Initialize per-action execution state.
842
+ b .readySema = make (chan bool , len (all ))
843
+ for _ , a := range all {
817
844
a .pending = len (a .deps )
818
845
if a .pending == 0 {
819
846
b .ready .push (a )
@@ -2761,7 +2788,7 @@ type actionQueue []*action
2761
2788
// Implement heap.Interface
2762
2789
func (q * actionQueue ) Len () int { return len (* q ) }
2763
2790
func (q * actionQueue ) Swap (i , j int ) { (* q )[i ], (* q )[j ] = (* q )[j ], (* q )[i ] }
2764
- func (q * actionQueue ) Less (i , j int ) bool { return (* q )[i ].priority < (* q )[j ].priority }
2791
+ func (q * actionQueue ) Less (i , j int ) bool { return (* q )[i ].priority > (* q )[j ].priority }
2765
2792
func (q * actionQueue ) Push (x interface {}) { * q = append (* q , x .(* action )) }
2766
2793
func (q * actionQueue ) Pop () interface {} {
2767
2794
n := len (* q ) - 1
0 commit comments