From a273333f1ff4993c11ae3477c4bde02909684ffb Mon Sep 17 00:00:00 2001 From: nolancon Date: Wed, 16 Jan 2019 14:05:42 +0000 Subject: [PATCH] Add BUILD files and Boilerplates Updates based on comments * Export comments added * glog changed to klog * Other small edits --- pkg/kubelet/cm/BUILD | 1 + pkg/kubelet/cm/topologymanager/BUILD | 23 ++ .../cm/topologymanager/socketmask/BUILD | 23 ++ .../topologymanager/socketmask/socketmask.go | 257 +++++++++--------- .../cm/topologymanager/socketmask_test.go | 104 +++++++ 5 files changed, 286 insertions(+), 122 deletions(-) create mode 100644 pkg/kubelet/cm/topologymanager/BUILD create mode 100644 pkg/kubelet/cm/topologymanager/socketmask/BUILD create mode 100644 pkg/kubelet/cm/topologymanager/socketmask_test.go diff --git a/pkg/kubelet/cm/BUILD b/pkg/kubelet/cm/BUILD index ee61d44d630..016820c19b3 100644 --- a/pkg/kubelet/cm/BUILD +++ b/pkg/kubelet/cm/BUILD @@ -166,6 +166,7 @@ filegroup( "//pkg/kubelet/cm/cpumanager:all-srcs", "//pkg/kubelet/cm/cpuset:all-srcs", "//pkg/kubelet/cm/devicemanager:all-srcs", + "//pkg/kubelet/cm/topologymanager:all-srcs", "//pkg/kubelet/cm/util:all-srcs", ], tags = ["automanaged"], diff --git a/pkg/kubelet/cm/topologymanager/BUILD b/pkg/kubelet/cm/topologymanager/BUILD new file mode 100644 index 00000000000..cfb40449b3b --- /dev/null +++ b/pkg/kubelet/cm/topologymanager/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_test") + +go_test( + name = "go_default_test", + srcs = ["socketmask_test.go"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/kubelet/cm/topologymanager/socketmask:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/kubelet/cm/topologymanager/socketmask/BUILD b/pkg/kubelet/cm/topologymanager/socketmask/BUILD new file mode 100644 index 00000000000..33791a89bb3 --- /dev/null +++ b/pkg/kubelet/cm/topologymanager/socketmask/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_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( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/kubelet/cm/topologymanager/socketmask/socketmask.go b/pkg/kubelet/cm/topologymanager/socketmask/socketmask.go index 02b580fd194..2e5056ccaf9 100644 --- a/pkg/kubelet/cm/topologymanager/socketmask/socketmask.go +++ b/pkg/kubelet/cm/topologymanager/socketmask/socketmask.go @@ -1,154 +1,167 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package socketmask import ( + "bytes" + "k8s.io/klog" + "math" "strconv" - "strings" - "bytes" - "math" - "github.com/golang/glog" + "strings" ) - +// SocketMask represents the NUMA affinity of a socket. type SocketMask []int64 +// NewSocketMask creates a new socket mask. func NewSocketMask(Mask []int64) SocketMask { - sm := Mask - return sm + return Mask } +// GetSocketMask calculates the socket mask. func (sm SocketMask) GetSocketMask(socketMask []SocketMask, maskHolder []string, count int) (SocketMask, []string) { var socketAffinityInt64 [][]int64 - for r := range socketMask { - socketAffinityVals := []int64(socketMask[r]) - socketAffinityInt64 = append(socketAffinityInt64,socketAffinityVals) - } - if count == 0 { - maskHolder = buildMaskHolder(socketAffinityInt64) + for r := range socketMask { + socketAffinityVals := []int64(socketMask[r]) + socketAffinityInt64 = append(socketAffinityInt64, socketAffinityVals) } - glog.Infof("[socketmask] MaskHolder : %v", maskHolder) - glog.Infof("[socketmask] %v is passed into arrange function", socketMask) - arrangedMask := arrangeMask(socketAffinityInt64) - newMask := getTopologyAffinity(arrangedMask, maskHolder) - glog.Infof("[socketmask] New Mask after getTopologyAffinity (new mask) : %v ",newMask) - finalMaskValue := parseMask(newMask) - glog.Infof("[socketmask] Mask []Int64 (finalMaskValue): %v", finalMaskValue) - maskHolder = newMask - glog.Infof("[socketmask] New MaskHolder: %v", maskHolder) - finalSocketMask := SocketMask(finalMaskValue) - return finalSocketMask, maskHolder + if count == 0 { + maskHolder = buildMaskHolder(socketAffinityInt64) + } + klog.V(4).Infof("[socketmask] MaskHolder : %v", maskHolder) + klog.V(4).Infof("[socketmask] %v is passed into arrange function", socketMask) + arrangedMask := arrangeMask(socketAffinityInt64) + 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 { - var maskHolder []string - outerLen := len(mask) - var innerLen int = 0 - for i := 0; i < outerLen; i++ { - if innerLen < len(mask[i]) { - innerLen = len(mask[i]) - } - } - 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 + outerLen := len(mask) + var innerLen int + for i := 0; i < outerLen; i++ { + 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) - } + 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 + return topologyResult } func parseMask(mask []string) []int64 { - var maskStr string - min := strings.Count(mask[0], "1") - var num, index int + 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 { - glog.Errorf("Could not convert string to int. Err: %v", err) - return maskInt - } - maskInt = append(maskInt, int64(convertedStr)) - } - glog.Infof("[socketmask] Mask Int in Parse Mask: %v", maskInt) - return maskInt + 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 { + 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() - } - return socketStr + 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() + } + 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) - } else { - val2 = val2 + strings.Repeat("0", num) - } - } - length := len(val1) - byteArr := make([]byte, length) - for i := 0; i < length ; i++ { - byteArr[i] = (val1[i] & val2[i]) - } - var finalStr string - finalStr = string(byteArr[:]) +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) + } else { + val2 = val2 + strings.Repeat("0", num) + } + } + length := len(val1) + byteArr := make([]byte, length) + for i := 0; i < length; i++ { + byteArr[i] = val1[i] & val2[i] + } - return finalStr + return string(byteArr[:]) } - diff --git a/pkg/kubelet/cm/topologymanager/socketmask_test.go b/pkg/kubelet/cm/topologymanager/socketmask_test.go new file mode 100644 index 00000000000..69a1efedf9e --- /dev/null +++ b/pkg/kubelet/cm/topologymanager/socketmask_test.go @@ -0,0 +1,104 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package socketmask + +import ( + "reflect" + "testing" +) + +func TestGetSocketmask(t *testing.T) { + tcases := []struct { + name string + socketmask []SocketMask + maskholder []string + count int + expectedMaskHolder []string + expectedFinalSocketMask SocketMask + }{ + { + name: "Empty MaskHolder and count set as 0", + socketmask: []SocketMask{{1, 0}, {0, 1}, {1, 1}}, + maskholder: []string{""}, + count: 0, + expectedMaskHolder: []string{"10", "01", "11"}, + expectedFinalSocketMask: SocketMask{1, 0}, + }, + { + name: "MaskHolder non zero, count set as 1", + socketmask: []SocketMask{{1, 0}, {0, 1}, {1, 1}}, + maskholder: []string{"10", "01", "11"}, + count: 1, + expectedMaskHolder: []string{"10", "01", "11"}, + expectedFinalSocketMask: SocketMask{1, 0}, + }, + + { + name: "Empty MaskHolder and count set as 0", + socketmask: []SocketMask{{0, 1}, {1, 1}}, + maskholder: []string{""}, + count: 0, + expectedMaskHolder: []string{"01", "11"}, + expectedFinalSocketMask: SocketMask{0, 1}, + }, + { + name: "MaskHolder non zero, count set as 1", + socketmask: []SocketMask{{0, 1}, {1, 1}}, + maskholder: []string{"01", "11"}, + count: 1, + expectedMaskHolder: []string{"01", "11"}, + expectedFinalSocketMask: SocketMask{0, 1}, + }, + } + + for _, tc := range tcases { + + sm := NewSocketMask(nil) + actualSocketMask, actualMaskHolder := sm.GetSocketMask(tc.socketmask, tc.maskholder, tc.count) + if !reflect.DeepEqual(actualSocketMask, tc.expectedFinalSocketMask) { + t.Errorf("Expected final socketmask to be %v, got %v", tc.expectedFinalSocketMask, actualSocketMask) + } + + if !reflect.DeepEqual(actualMaskHolder, tc.expectedMaskHolder) { + t.Errorf("Expected maskholder to be %v, got %v", tc.expectedMaskHolder, actualMaskHolder) + } + + } +} + +func TestNewSocketMask(t *testing.T) { + tcases := []struct { + name string + Mask []int64 + expectedMask []int64 + }{ + { + name: "Mask as an int64 binary array", + Mask: []int64{1, 0}, + expectedMask: []int64{1, 0}, + }, + } + + for _, tc := range tcases { + + sm := NewSocketMask(nil) + + if reflect.DeepEqual(sm, tc.expectedMask) { + t.Errorf("Expected socket mask to be %v, got %v", tc.expectedMask, sm) + } + } +}