mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +00:00
Improved FormatMap: Improves performance by about 4x, or nearly 2x in the worst case (#112661)
* Improved FormatMap Improves performance by about 4x, or nearly 2x in the worst case old FormatMap BenchmarkFormatMap-12 873046 1238 ns/op 384 B/op 13 allocs/op new FormatMap BenchmarkFormatMap-12 3665762 327.0 ns/op 152 B/op 3 allocs/op Signed-off-by: aimuz <mr.imuz@gmail.com> * fixed Signed-off-by: aimuz <mr.imuz@gmail.com> * fixed Signed-off-by: aimuz <mr.imuz@gmail.com> * test: fix test Signed-off-by: aimuz <mr.imuz@gmail.com> --------- Signed-off-by: aimuz <mr.imuz@gmail.com>
This commit is contained in:
parent
d788d436c9
commit
571adf6e84
@ -18,26 +18,36 @@ package fieldpath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
)
|
||||
|
||||
// FormatMap formats map[string]string to a string.
|
||||
func FormatMap(m map[string]string) (fmtStr string) {
|
||||
// output with keys in sorted order to provide stable output
|
||||
keys := sets.NewString()
|
||||
for key := range m {
|
||||
keys.Insert(key)
|
||||
keys := make([]string, 0, len(m))
|
||||
var grow int
|
||||
for k, v := range m {
|
||||
keys = append(keys, k)
|
||||
// why add 4: (for =, \n, " and ")
|
||||
grow += len(k) + len(v) + 4
|
||||
}
|
||||
for _, key := range keys.List() {
|
||||
fmtStr += fmt.Sprintf("%v=%q\n", key, m[key])
|
||||
sort.Strings(keys)
|
||||
// allocate space to avoid expansion
|
||||
dst := make([]byte, 0, grow)
|
||||
for _, key := range keys {
|
||||
if len(dst) > 0 {
|
||||
dst = append(dst, '\n')
|
||||
}
|
||||
dst = append(dst, key...)
|
||||
dst = append(dst, '=')
|
||||
dst = strconv.AppendQuote(dst, m[key])
|
||||
}
|
||||
fmtStr = strings.TrimSuffix(fmtStr, "\n")
|
||||
|
||||
return
|
||||
return string(dst)
|
||||
}
|
||||
|
||||
// ExtractFieldPathAsString extracts the field from the given object
|
||||
|
@ -24,6 +24,30 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func BenchmarkFormatMap(b *testing.B) {
|
||||
var s string
|
||||
m := map[string]string{
|
||||
"spec.pod.beta.kubernetes.io/statefulset-index": "1",
|
||||
"Www.k8s.io/test": "1",
|
||||
"foo": "bar",
|
||||
"flannel.alpha.coreos.com/backend-data": `{"VNI":1,"VtepMAC":"ce:f9:c7:a4:de:64"}`,
|
||||
"flannel.alpha.coreos.com/backend-type": "vxlan",
|
||||
"flannel.alpha.coreos.com/kube-subnet-manager": "true",
|
||||
"flannel.alpha.coreos.com/public-ip": "192.168.19.160",
|
||||
"management.cattle.io/pod-limits": `{"cpu":"11400m","memory":"7965Mi"}`,
|
||||
"management.cattle.io/pod-requests": `{"cpu":"2482m","memory":"7984Mi","pods":"26"}`,
|
||||
"node.alpha.kubernetes.io/ttl": "0",
|
||||
"volumes.kubernetes.io/controller-managed-attach-detach": "true",
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
s = FormatMap(m)
|
||||
}
|
||||
// Avoid compiler optimizations
|
||||
_ = s
|
||||
}
|
||||
|
||||
func TestExtractFieldPathAsString(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
@ -268,3 +292,72 @@ func TestSplitMaybeSubscriptedPath(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestFormatMap
|
||||
func TestFormatMap(t *testing.T) {
|
||||
type args struct {
|
||||
m map[string]string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantFmtStr string
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
args: args{
|
||||
m: nil,
|
||||
},
|
||||
wantFmtStr: "",
|
||||
},
|
||||
{
|
||||
name: "label",
|
||||
args: args{
|
||||
m: map[string]string{
|
||||
"beta.kubernetes.io/os": "linux",
|
||||
"kubernetes.io/arch": "amd64",
|
||||
"kubernetes.io/hostname": "master01",
|
||||
"kubernetes.io/os": "linux",
|
||||
"node-role.kubernetes.io/control-plane": "true",
|
||||
"node-role.kubernetes.io/master": "true",
|
||||
},
|
||||
},
|
||||
wantFmtStr: `beta.kubernetes.io/os="linux"
|
||||
kubernetes.io/arch="amd64"
|
||||
kubernetes.io/hostname="master01"
|
||||
kubernetes.io/os="linux"
|
||||
node-role.kubernetes.io/control-plane="true"
|
||||
node-role.kubernetes.io/master="true"`,
|
||||
},
|
||||
{
|
||||
name: "annotation",
|
||||
args: args{
|
||||
m: map[string]string{
|
||||
"flannel.alpha.coreos.com/backend-data": `{"VNI":1,"VtepMAC":"ce:f9:c7:a4:de:64"}`,
|
||||
"flannel.alpha.coreos.com/backend-type": "vxlan",
|
||||
"flannel.alpha.coreos.com/kube-subnet-manager": "true",
|
||||
"flannel.alpha.coreos.com/public-ip": "192.168.19.160",
|
||||
"management.cattle.io/pod-limits": `{"cpu":"11400m","memory":"7965Mi"}`,
|
||||
"management.cattle.io/pod-requests": `{"cpu":"2482m","memory":"7984Mi","pods":"26"}`,
|
||||
"node.alpha.kubernetes.io/ttl": "0",
|
||||
"volumes.kubernetes.io/controller-managed-attach-detach": "true",
|
||||
},
|
||||
},
|
||||
wantFmtStr: `flannel.alpha.coreos.com/backend-data="{\"VNI\":1,\"VtepMAC\":\"ce:f9:c7:a4:de:64\"}"
|
||||
flannel.alpha.coreos.com/backend-type="vxlan"
|
||||
flannel.alpha.coreos.com/kube-subnet-manager="true"
|
||||
flannel.alpha.coreos.com/public-ip="192.168.19.160"
|
||||
management.cattle.io/pod-limits="{\"cpu\":\"11400m\",\"memory\":\"7965Mi\"}"
|
||||
management.cattle.io/pod-requests="{\"cpu\":\"2482m\",\"memory\":\"7984Mi\",\"pods\":\"26\"}"
|
||||
node.alpha.kubernetes.io/ttl="0"
|
||||
volumes.kubernetes.io/controller-managed-attach-detach="true"`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotFmtStr := FormatMap(tt.args.m); gotFmtStr != tt.wantFmtStr {
|
||||
t.Errorf("FormatMap() = %v, want %v", gotFmtStr, tt.wantFmtStr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user