mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #39527 from kargakis/tests-and-benchmarks-for-adler-and-fnv
Automatic merge from submit-queue (batch tested with PRs 39466, 39490, 39527) Test and benchmark adler and fnv Split out of https://github.com/kubernetes/kubernetes/pull/38714 @kubernetes/sig-apps-misc
This commit is contained in:
		@@ -44,7 +44,10 @@ go_library(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
go_test(
 | 
					go_test(
 | 
				
			||||||
    name = "go_default_test",
 | 
					    name = "go_default_test",
 | 
				
			||||||
    srcs = ["deployment_util_test.go"],
 | 
					    srcs = [
 | 
				
			||||||
 | 
					        "deployment_util_test.go",
 | 
				
			||||||
 | 
					        "hash_test.go",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
    library = ":go_default_library",
 | 
					    library = ":go_default_library",
 | 
				
			||||||
    tags = ["automanaged"],
 | 
					    tags = ["automanaged"],
 | 
				
			||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										158
									
								
								pkg/controller/deployment/util/hash_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								pkg/controller/deployment/util/hash_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,158 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2016 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 util
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/v1"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var podSpec string = `
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    "metadata": {
 | 
				
			||||||
 | 
					        "creationTimestamp": null,
 | 
				
			||||||
 | 
					        "labels": {
 | 
				
			||||||
 | 
					            "app": "cats"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "spec": {
 | 
				
			||||||
 | 
					        "containers": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "name": "cats",
 | 
				
			||||||
 | 
					                "image": "registry/test/cats:v0.@@VERSION@@.0",
 | 
				
			||||||
 | 
					                "ports": [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        "name": "http",
 | 
				
			||||||
 | 
					                        "containerPort": 9077,
 | 
				
			||||||
 | 
					                        "protocol": "TCP"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                "env": [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        "name": "DEPLOYMENT_ENVIRONMENT",
 | 
				
			||||||
 | 
					                        "value": "cats-stubbed-functional"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        "name": "APP_NAME",
 | 
				
			||||||
 | 
					                        "value": "cats"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                "resources": {
 | 
				
			||||||
 | 
					                    "limits": {
 | 
				
			||||||
 | 
					                        "cpu": "1",
 | 
				
			||||||
 | 
					                        "memory": "1Gi"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "requests": {
 | 
				
			||||||
 | 
					                        "cpu": "1",
 | 
				
			||||||
 | 
					                        "memory": "1Gi"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "livenessProbe": {
 | 
				
			||||||
 | 
					                    "httpGet": {
 | 
				
			||||||
 | 
					                        "path": "/private/status",
 | 
				
			||||||
 | 
					                        "port": 9077,
 | 
				
			||||||
 | 
					                        "scheme": "HTTP"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "initialDelaySeconds": 30,
 | 
				
			||||||
 | 
					                    "timeoutSeconds": 1,
 | 
				
			||||||
 | 
					                    "periodSeconds": 10,
 | 
				
			||||||
 | 
					                    "successThreshold": 1,
 | 
				
			||||||
 | 
					                    "failureThreshold": 3
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "readinessProbe": {
 | 
				
			||||||
 | 
					                    "httpGet": {
 | 
				
			||||||
 | 
					                        "path": "/private/status",
 | 
				
			||||||
 | 
					                        "port": 9077,
 | 
				
			||||||
 | 
					                        "scheme": "HTTP"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "initialDelaySeconds": 1,
 | 
				
			||||||
 | 
					                    "timeoutSeconds": 1,
 | 
				
			||||||
 | 
					                    "periodSeconds": 10,
 | 
				
			||||||
 | 
					                    "successThreshold": 1,
 | 
				
			||||||
 | 
					                    "failureThreshold": 3
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "terminationMessagePath": "/dev/termination-log",
 | 
				
			||||||
 | 
					                "imagePullPolicy": "IfNotPresent"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "restartPolicy": "Always",
 | 
				
			||||||
 | 
					        "terminationGracePeriodSeconds": 30,
 | 
				
			||||||
 | 
					        "dnsPolicy": "ClusterFirst",
 | 
				
			||||||
 | 
					        "securityContext": {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPodTemplateSpecHash(t *testing.T) {
 | 
				
			||||||
 | 
						seenHashes := make(map[uint32]int)
 | 
				
			||||||
 | 
						broken := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < 1000; i++ {
 | 
				
			||||||
 | 
							specJson := strings.Replace(podSpec, "@@VERSION@@", strconv.Itoa(i), 1)
 | 
				
			||||||
 | 
							spec := v1.PodTemplateSpec{}
 | 
				
			||||||
 | 
							json.Unmarshal([]byte(specJson), &spec)
 | 
				
			||||||
 | 
							hash := GetPodTemplateSpecHash(spec)
 | 
				
			||||||
 | 
							if v, ok := seenHashes[hash]; ok {
 | 
				
			||||||
 | 
								broken = true
 | 
				
			||||||
 | 
								t.Logf("Hash collision, old: %d new: %d", v, i)
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							seenHashes[hash] = i
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !broken {
 | 
				
			||||||
 | 
							t.Errorf("expected adler to break but it didn't")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPodTemplateSpecHashFnv(t *testing.T) {
 | 
				
			||||||
 | 
						seenHashes := make(map[uint32]int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < 1000; i++ {
 | 
				
			||||||
 | 
							specJson := strings.Replace(podSpec, "@@VERSION@@", strconv.Itoa(i), 1)
 | 
				
			||||||
 | 
							spec := v1.PodTemplateSpec{}
 | 
				
			||||||
 | 
							json.Unmarshal([]byte(specJson), &spec)
 | 
				
			||||||
 | 
							hash := GetPodTemplateSpecHashFnv(spec)
 | 
				
			||||||
 | 
							if v, ok := seenHashes[hash]; ok {
 | 
				
			||||||
 | 
								t.Errorf("Hash collision, old: %d new: %d", v, i)
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							seenHashes[hash] = i
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkAdler(b *testing.B) {
 | 
				
			||||||
 | 
						spec := v1.PodTemplateSpec{}
 | 
				
			||||||
 | 
						json.Unmarshal([]byte(podSpec), &spec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							GetPodTemplateSpecHash(spec)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkFnv(b *testing.B) {
 | 
				
			||||||
 | 
						spec := v1.PodTemplateSpec{}
 | 
				
			||||||
 | 
						json.Unmarshal([]byte(podSpec), &spec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							GetPodTemplateSpecHashFnv(spec)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -18,6 +18,7 @@ package util
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"hash/adler32"
 | 
						"hash/adler32"
 | 
				
			||||||
 | 
						"hash/fnv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -43,6 +44,12 @@ func GetInternalPodTemplateSpecHash(template api.PodTemplateSpec) uint32 {
 | 
				
			|||||||
	return podTemplateSpecHasher.Sum32()
 | 
						return podTemplateSpecHasher.Sum32()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetPodTemplateSpecHashFnv(template v1.PodTemplateSpec) uint32 {
 | 
				
			||||||
 | 
						podTemplateSpecHasher := fnv.New32a()
 | 
				
			||||||
 | 
						hashutil.DeepHashObject(podTemplateSpecHasher, template)
 | 
				
			||||||
 | 
						return podTemplateSpecHasher.Sum32()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: use client library instead when it starts to support update retries
 | 
					// TODO: use client library instead when it starts to support update retries
 | 
				
			||||||
//       see https://github.com/kubernetes/kubernetes/issues/21479
 | 
					//       see https://github.com/kubernetes/kubernetes/issues/21479
 | 
				
			||||||
type updatePodFunc func(pod *v1.Pod) error
 | 
					type updatePodFunc func(pod *v1.Pod) error
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,3 +77,13 @@ func GetReplicaSetHash(rs *extensions.ReplicaSet) string {
 | 
				
			|||||||
		Spec:       rs.Spec.Template.Spec,
 | 
							Spec:       rs.Spec.Template.Spec,
 | 
				
			||||||
	}))
 | 
						}))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetReplicaSetHashFnv returns the pod template hash of a ReplicaSet's pod template spec.
 | 
				
			||||||
 | 
					func GetReplicaSetHashFnv(rs *extensions.ReplicaSet) string {
 | 
				
			||||||
 | 
						meta := rs.Spec.Template.ObjectMeta
 | 
				
			||||||
 | 
						meta.Labels = labelsutil.CloneAndRemoveLabel(meta.Labels, extensions.DefaultDeploymentUniqueLabelKey)
 | 
				
			||||||
 | 
						return fmt.Sprintf("%d", GetPodTemplateSpecHashFnv(v1.PodTemplateSpec{
 | 
				
			||||||
 | 
							ObjectMeta: meta,
 | 
				
			||||||
 | 
							Spec:       rs.Spec.Template.Spec,
 | 
				
			||||||
 | 
						}))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user