diff --git a/api/allocations.go b/api/allocations.go index 95a748f0e..a3a830481 100644 --- a/api/allocations.go +++ b/api/allocations.go @@ -109,10 +109,11 @@ type AllocationMetric struct { ClassExhausted map[string]int DimensionExhausted map[string]int QuotaExhausted []string - Scores map[string]float64 - AllocationTime time.Duration - CoalescedFailures int - ScoreMetaData []*NodeScoreMeta + // Deprecated, replaced with ScoreMetaData + Scores map[string]float64 + AllocationTime time.Duration + CoalescedFailures int + ScoreMetaData []*NodeScoreMeta } // NodeScoreMeta is used to serialize node scoring metadata diff --git a/lib/kheap/score_heap.go b/lib/kheap/score_heap.go index 9ad9e0b3a..216ae7043 100644 --- a/lib/kheap/score_heap.go +++ b/lib/kheap/score_heap.go @@ -61,3 +61,16 @@ func (pq *ScoreHeap) Pop() interface{} { pq.items = old[0 : n-1] return item } + +// GetItemsReverse returns the items in this min heap in reverse order +// sorted by score descending +func (pq *ScoreHeap) GetItemsReverse() []interface{} { + ret := make([]interface{}, pq.Len()) + i := pq.Len() - 1 + for pq.Len() > 0 { + item := heap.Pop(pq) + ret[i] = item + i-- + } + return ret +} diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 105d39334..3e35acc3c 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -6618,13 +6618,9 @@ func (a *AllocMetric) PopulateScoreMetaData() { if a.ScoreMetaData == nil { a.ScoreMetaData = make([]*NodeScoreMeta, a.topScores.Len()) } - i := a.topScores.Len() - 1 - // Pop from the heap and store in reverse to get top K - // scoring nodes in descending order - for a.topScores.Len() > 0 { - item := heap.Pop(a.topScores).(*NodeScoreMeta) - a.ScoreMetaData[i] = item - i-- + heapItems := a.topScores.GetItemsReverse() + for i, item := range heapItems { + a.ScoreMetaData[i] = item.(*NodeScoreMeta) } } } diff --git a/scheduler/system_sched.go b/scheduler/system_sched.go index 4a10d0731..7a84bd8a9 100644 --- a/scheduler/system_sched.go +++ b/scheduler/system_sched.go @@ -304,6 +304,9 @@ func (s *SystemScheduler) computePlacements(place []allocTuple) error { // Store the available nodes by datacenter s.ctx.Metrics().NodesAvailable = s.nodesByDC + // Compute top K scoring node metadata + s.ctx.Metrics().PopulateScoreMetaData() + // Set fields based on if we found an allocation option if option != nil { // Create an allocation for this