...
1
16
17 package topologymanager
18
19 import (
20 "fmt"
21
22 cadvisorapi "github.com/google/cadvisor/info/v1"
23 "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager/bitmask"
24 )
25
26 type NUMADistances map[int][]uint64
27
28 type NUMAInfo struct {
29 Nodes []int
30 NUMADistances NUMADistances
31 }
32
33 func NewNUMAInfo(topology []cadvisorapi.Node, opts PolicyOptions) (*NUMAInfo, error) {
34 var numaNodes []int
35 distances := map[int][]uint64{}
36 for _, node := range topology {
37 numaNodes = append(numaNodes, node.Id)
38
39 var nodeDistance []uint64
40 if opts.PreferClosestNUMA {
41 nodeDistance = node.Distances
42 if nodeDistance == nil {
43 return nil, fmt.Errorf("error getting NUMA distances from cadvisor")
44 }
45 }
46 distances[node.Id] = nodeDistance
47 }
48
49 numaInfo := &NUMAInfo{
50 Nodes: numaNodes,
51 NUMADistances: distances,
52 }
53
54 return numaInfo, nil
55 }
56
57 func (n *NUMAInfo) Narrowest(m1 bitmask.BitMask, m2 bitmask.BitMask) bitmask.BitMask {
58 if m1.IsNarrowerThan(m2) {
59 return m1
60 }
61 return m2
62 }
63
64 func (n *NUMAInfo) Closest(m1 bitmask.BitMask, m2 bitmask.BitMask) bitmask.BitMask {
65
66 if m1.Count() != m2.Count() {
67 return n.Narrowest(m1, m2)
68 }
69
70 m1Distance := n.NUMADistances.CalculateAverageFor(m1)
71 m2Distance := n.NUMADistances.CalculateAverageFor(m2)
72
73 if m1Distance == m2Distance {
74 if m1.IsLessThan(m2) {
75 return m1
76 }
77 return m2
78 }
79
80
81 if m1Distance < m2Distance {
82 return m1
83 }
84
85 return m2
86 }
87
88 func (n NUMAInfo) DefaultAffinityMask() bitmask.BitMask {
89 defaultAffinity, _ := bitmask.NewBitMask(n.Nodes...)
90 return defaultAffinity
91 }
92
93 func (d NUMADistances) CalculateAverageFor(bm bitmask.BitMask) float64 {
94
95 if bm.Count() == 0 {
96 return 0
97 }
98
99 var count float64 = 0
100 var sum float64 = 0
101 for _, node1 := range bm.GetBits() {
102 for _, node2 := range bm.GetBits() {
103 sum += float64(d[node1][node2])
104 count++
105 }
106 }
107
108 return sum / count
109 }
110
View as plain text