Update SocketMask based on feedback

TODO: Unit tests to be updated
This commit is contained in:
nolancon 2019-05-27 04:23:13 +01:00
parent e8566caa3f
commit 283dff9335
2 changed files with 108 additions and 119 deletions

View File

@ -5,7 +5,6 @@ go_library(
srcs = ["socketmask.go"], srcs = ["socketmask.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager/socketmask", importpath = "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager/socketmask",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = ["//vendor/k8s.io/klog:go_default_library"],
) )
filegroup( filegroup(

View File

@ -17,146 +17,136 @@ limitations under the License.
package socketmask package socketmask
import ( import (
"bytes" "fmt"
"k8s.io/klog"
"math"
"strconv"
"strings"
) )
// SocketMask represents the NUMA affinity of a socket. //SocketMask interface allows hint providers to create SocketMasks for TopologyHints
type SocketMask []int64 type SocketMask interface {
Add(sockets ...int) error
// NewSocketMask creates a new socket mask. Remove(sockets ...int) error
func NewSocketMask(Mask []int64) SocketMask { And(masks ...SocketMask)
return Mask 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. type socketMask uint64
func (sm SocketMask) GetSocketMask(socketMaskInt64 [][]int64, maskHolder []string, count int) (SocketMask, []string) {
if count == 0 {
maskHolder = buildMaskHolder(socketMaskInt64)
}
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
}
func buildMaskHolder(mask [][]int64) []string { //NewSocketMask creates a new SocketMask
outerLen := len(mask) func NewSocketMask(sockets ...int) (SocketMask, error) {
var innerLen int s := socketMask(0)
for i := 0; i < outerLen; i++ { err := (&s).Add(sockets...)
if innerLen < len(mask[i]) {
innerLen = len(mask[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
}
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)
}
}
}
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
}
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]
}
var maskInt []int64
for _, char := range maskStr {
convertedStr, err := strconv.Atoi(string(char))
if err != nil { if err != nil {
klog.V(4).Infof("could not convert mask character: %v", err) return nil, err
return maskInt
} }
maskInt = append(maskInt, int64(convertedStr)) return &s, nil
}
klog.V(4).Infof("[socketmask] Mask Int in Parse Mask: %v", maskInt)
return maskInt
} }
func arrangeMask(mask [][]int64) []string { //Add adds the sockets with topology affinity to the SocketMask
var socketStr []string func (s *socketMask) Add(sockets ...int) error {
var bufferNew bytes.Buffer mask := *s
outerLen := len(mask) for _, i := range sockets {
innerLen := len(mask[0]) if i < 0 || i >= 64 {
for i := 0; i < outerLen; i++ { return fmt.Errorf("socket number must be in range 0-63")
for j := 0; j < innerLen; j++ {
if mask[i][j] == 1 {
bufferNew.WriteString("1")
} else if mask[i][j] == 0 {
bufferNew.WriteString("0")
} }
mask |= 1 << uint64(i)
} }
socketStr = append(socketStr, bufferNew.String()) *s = mask
bufferNew.Reset() return nil
}
return socketStr
} }
func andOperation(val1, val2 string) string { //Remove removes specified sockets from SocketMask
l1, l2 := len(val1), len(val2) func (s *socketMask) Remove(sockets ...int) error {
//compare lengths of strings - pad shortest with trailing zeros mask := *s
if l1 != l2 { for _, i := range sockets {
// Get the bit difference if i < 0 || i >= 64 {
var num int return fmt.Errorf("socket number must be in range 0-63")
diff := math.Abs(float64(l1) - float64(l2)) }
num = int(diff) mask &^= 1 << uint64(i)
if l1 < l2 { }
val1 = val1 + strings.Repeat("0", num) *s = mask
return nil
}
//And performs and operation on all bits in masks
func (s *socketMask) And(masks ...SocketMask) {
for _, m := range masks {
*s &= *m.(*socketMask)
}
}
//Or performs or operation on all bits in masks
func (s *socketMask) Or(masks ...SocketMask) {
for _, m := range masks {
*s |= *m.(*socketMask)
}
}
//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 { } else {
val2 = val2 + strings.Repeat("0", num) str += "0"
} }
} }
length := len(val1) return str
byteArr := make([]byte, length)
for i := 0; i < length; i++ {
byteArr[i] = val1[i] & val2[i]
} }
return string(byteArr[:]) //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
} }