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:
aimuz 2023-03-02 14:26:55 +08:00 committed by GitHub
parent d788d436c9
commit 571adf6e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 112 additions and 9 deletions

View File

@ -18,26 +18,36 @@ package fieldpath
import ( import (
"fmt" "fmt"
"sort"
"strconv"
"strings" "strings"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation"
) )
// FormatMap formats map[string]string to a string. // FormatMap formats map[string]string to a string.
func FormatMap(m map[string]string) (fmtStr string) { func FormatMap(m map[string]string) (fmtStr string) {
// output with keys in sorted order to provide stable output // output with keys in sorted order to provide stable output
keys := sets.NewString() keys := make([]string, 0, len(m))
for key := range m { var grow int
keys.Insert(key) 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() { sort.Strings(keys)
fmtStr += fmt.Sprintf("%v=%q\n", key, m[key]) // 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 string(dst)
return
} }
// ExtractFieldPathAsString extracts the field from the given object // ExtractFieldPathAsString extracts the field from the given object

View File

@ -24,6 +24,30 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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) { func TestExtractFieldPathAsString(t *testing.T) {
cases := []struct { cases := []struct {
name string 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)
}
})
}
}