From 283dff9335011fdc30aef0051af346123d9abf54 Mon Sep 17 00:00:00 2001 From: nolancon Date: Mon, 27 May 2019 04:23:13 +0100 Subject: [PATCH] Update SocketMask based on feedback TODO: Unit tests to be updated --- .../cm/topologymanager/socketmask/BUILD | 1 - .../topologymanager/socketmask/socketmask.go | 226 +++++++++--------- 2 files changed, 108 insertions(+), 119 deletions(-) diff --git a/pkg/kubelet/cm/topologymanager/socketmask/BUILD b/pkg/kubelet/cm/topologymanager/socketmask/BUILD index 0e49d414b8c..25bd381e862 100644 --- a/pkg/kubelet/cm/topologymanager/socketmask/BUILD +++ b/pkg/kubelet/cm/topologymanager/socketmask/BUILD @@ -5,7 +5,6 @@ go_library( srcs = ["socketmask.go"], importpath = "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager/socketmask", visibility = ["//visibility:public"], - deps = ["//vendor/k8s.io/klog:go_default_library"], ) filegroup( diff --git a/pkg/kubelet/cm/topologymanager/socketmask/socketmask.go b/pkg/kubelet/cm/topologymanager/socketmask/socketmask.go index c6f483932df..8e74ce0291a 100644 --- a/pkg/kubelet/cm/topologymanager/socketmask/socketmask.go +++ b/pkg/kubelet/cm/topologymanager/socketmask/socketmask.go @@ -17,146 +17,136 @@ limitations under the License. package socketmask import ( - "bytes" - "k8s.io/klog" - "math" - "strconv" - "strings" + "fmt" ) -// SocketMask represents the NUMA affinity of a socket. -type SocketMask []int64 - -// NewSocketMask creates a new socket mask. -func NewSocketMask(Mask []int64) SocketMask { - return Mask +//SocketMask interface allows hint providers to create SocketMasks for TopologyHints +type SocketMask interface { + Add(sockets ...int) error + Remove(sockets ...int) error + And(masks ...SocketMask) + Or(masks ...SocketMask) + Clear() + Fill() + IsEqual(mask SocketMask) bool + IsEmpty() bool + IsSet(socket int) bool + String() string + Count() int + GetSockets() []int } -// GetSocketMask calculates the socket mask. -func (sm SocketMask) GetSocketMask(socketMaskInt64 [][]int64, maskHolder []string, count int) (SocketMask, []string) { - if count == 0 { - maskHolder = buildMaskHolder(socketMaskInt64) +type socketMask uint64 + +//NewSocketMask creates a new SocketMask +func NewSocketMask(sockets ...int) (SocketMask, error) { + s := socketMask(0) + err := (&s).Add(sockets...) + if err != nil { + return nil, err } - klog.V(4).Infof("[socketmask] MaskHolder : %v", maskHolder) - klog.V(4).Infof("[socketmask] %v is passed into arrange function", socketMaskInt64) - arrangedMask := arrangeMask(socketMaskInt64) - newMask := getTopologyAffinity(arrangedMask, maskHolder) - klog.V(4).Infof("[socketmask] New Mask after getTopologyAffinity (new mask) : %v ", newMask) - finalMaskValue := parseMask(newMask) - klog.V(4).Infof("[socketmask] Mask []Int64 (finalMaskValue): %v", finalMaskValue) - maskHolder = newMask - klog.V(4).Infof("[socketmask] New MaskHolder: %v", maskHolder) - return SocketMask(finalMaskValue), maskHolder + return &s, nil } -func buildMaskHolder(mask [][]int64) []string { - outerLen := len(mask) - var innerLen int - for i := 0; i < outerLen; i++ { - if innerLen < len(mask[i]) { - innerLen = len(mask[i]) +//Add adds the sockets with topology affinity to the SocketMask +func (s *socketMask) Add(sockets ...int) error { + mask := *s + for _, i := range sockets { + if i < 0 || i >= 64 { + return fmt.Errorf("socket number must be in range 0-63") } + mask |= 1 << uint64(i) } - var maskHolder []string - var buffer bytes.Buffer - var i, j int = 0, 0 - for i = 0; i < outerLen; i++ { - for j = 0; j < innerLen; j++ { - buffer.WriteString("1") - } - maskHolder = append(maskHolder, buffer.String()) - buffer.Reset() - } - return maskHolder + *s = mask + return nil } -func getTopologyAffinity(arrangedMask, maskHolder []string) []string { - var topologyTemp []string - for i := 0; i < len(maskHolder); i++ { - for j := 0; j < len(arrangedMask); j++ { - tempStr := andOperation(maskHolder[i], arrangedMask[j]) - if strings.Contains(tempStr, "1") { - topologyTemp = append(topologyTemp, tempStr) - } +//Remove removes specified sockets from SocketMask +func (s *socketMask) Remove(sockets ...int) error { + mask := *s + for _, i := range sockets { + if i < 0 || i >= 64 { + return fmt.Errorf("socket number must be in range 0-63") } + mask &^= 1 << uint64(i) } - duplicates := map[string]bool{} - for v := range topologyTemp { - duplicates[topologyTemp[v]] = true - } - // Place all keys from the map into a slice. - topologyResult := []string{} - for key := range duplicates { - topologyResult = append(topologyResult, key) - } - - return topologyResult + *s = mask + return nil } -func parseMask(mask []string) []int64 { - var maskStr string - min := strings.Count(mask[0], "1") - var num, index int - - for i := 0; i < len(mask); i++ { - num = strings.Count(mask[i], "1") - if num < min { - min = num - index = i - } - maskStr = mask[index] +//And performs and operation on all bits in masks +func (s *socketMask) And(masks ...SocketMask) { + for _, m := range masks { + *s &= *m.(*socketMask) } - var maskInt []int64 - for _, char := range maskStr { - convertedStr, err := strconv.Atoi(string(char)) - if err != nil { - klog.V(4).Infof("could not convert mask character: %v", err) - return maskInt - } - maskInt = append(maskInt, int64(convertedStr)) - } - klog.V(4).Infof("[socketmask] Mask Int in Parse Mask: %v", maskInt) - return maskInt } -func arrangeMask(mask [][]int64) []string { - var socketStr []string - var bufferNew bytes.Buffer - outerLen := len(mask) - innerLen := len(mask[0]) - for i := 0; i < outerLen; i++ { - for j := 0; j < innerLen; j++ { - if mask[i][j] == 1 { - bufferNew.WriteString("1") - } else if mask[i][j] == 0 { - bufferNew.WriteString("0") - } - } - socketStr = append(socketStr, bufferNew.String()) - bufferNew.Reset() +//Or performs or operation on all bits in masks +func (s *socketMask) Or(masks ...SocketMask) { + for _, m := range masks { + *s |= *m.(*socketMask) } - return socketStr } -func andOperation(val1, val2 string) string { - l1, l2 := len(val1), len(val2) - //compare lengths of strings - pad shortest with trailing zeros - if l1 != l2 { - // Get the bit difference - var num int - diff := math.Abs(float64(l1) - float64(l2)) - num = int(diff) - if l1 < l2 { - val1 = val1 + strings.Repeat("0", num) +//Clear resets all bits in mask to zero +func (s *socketMask) Clear() { + *s = 0 +} + +//Fill sets all bits in mask to one +func (s *socketMask) Fill() { + *s = socketMask(^uint64(0)) +} + +//IsEmpty checks mask to see if all bits are zero +func (s *socketMask) IsEmpty() bool { + return *s == 0 +} + +//IsSet checks socket in mask to see if bit is set to one +func (s *socketMask) IsSet(socket int) bool { + if socket < 0 || socket >= 64 { + return false + } + return (*s & (1 << uint64(socket))) > 0 +} + +//IsEqual checks if masks are equal +func (s *socketMask) IsEqual(mask SocketMask) bool { + return *s == *mask.(*socketMask) +} + +//String converts mask to string +func (s *socketMask) String() string { + str := "" + for i := uint64(0); i < 64; i++ { + if (*s & (1 << i)) > 0 { + str += "1" } else { - val2 = val2 + strings.Repeat("0", num) + str += "0" } } - length := len(val1) - byteArr := make([]byte, length) - for i := 0; i < length; i++ { - byteArr[i] = val1[i] & val2[i] - } - - return string(byteArr[:]) + return str +} + +//Count counts number of bits in mask set to one +func (s *socketMask) Count() int { + count := 0 + for i := uint64(0); i < 64; i++ { + if (*s & (1 << i)) > 0 { + count++ + } + } + return count +} + +//GetSockets returns each socket number with bits set to one +func (s *socketMask) GetSockets() []int { + var sockets []int + for i := uint64(0); i < 64; i++ { + if (*s & (1 << i)) > 0 { + sockets = append(sockets, int(i)) + } + } + return sockets }