Add a benchmark for pod creation
This adds a benchmark for pod creation and makes the mock_test provider actually work correctly in concurrent situations.
This commit is contained in:
1
go.mod
1
go.mod
@@ -28,6 +28,7 @@ require (
|
|||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
github.com/onsi/ginkgo v1.8.0 // indirect
|
github.com/onsi/ginkgo v1.8.0 // indirect
|
||||||
github.com/onsi/gomega v1.5.0 // indirect
|
github.com/onsi/gomega v1.5.0 // indirect
|
||||||
|
github.com/pborman/uuid v1.2.0 // indirect
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/sirupsen/logrus v1.4.1
|
github.com/sirupsen/logrus v1.4.1
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -68,6 +68,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
|||||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
|
||||||
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
|
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
|
||||||
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
@@ -125,6 +127,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
|||||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
|
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
||||||
|
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
kubeinformers "k8s.io/client-go/informers"
|
kubeinformers "k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
@@ -414,8 +415,51 @@ func testCreateStartDeleteScenario(ctx context.Context, t *testing.T, s *system)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPod() *corev1.Pod {
|
func BenchmarkCreatePods(b *testing.B) {
|
||||||
return &corev1.Pod{
|
sl := logrus.StandardLogger()
|
||||||
|
sl.SetLevel(logrus.ErrorLevel)
|
||||||
|
newLogger := logruslogger.FromLogrus(logrus.NewEntry(sl))
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx = log.WithLogger(ctx, newLogger)
|
||||||
|
|
||||||
|
assert.NilError(b, wireUpSystem(ctx, newMockProvider(), func(ctx context.Context, s *system) {
|
||||||
|
benchmarkCreatePods(ctx, b, s)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkCreatePods(ctx context.Context, b *testing.B, s *system) {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
errCh := s.start(ctx)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
pod := newPod(randomizeUID, randomizeName)
|
||||||
|
_, err := s.client.CoreV1().Pods(pod.Namespace).Create(pod)
|
||||||
|
assert.NilError(b, err)
|
||||||
|
select {
|
||||||
|
case err = <-errCh:
|
||||||
|
b.Fatalf("Benchmark terminated with error: %+v", err)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type podModifier func(*corev1.Pod)
|
||||||
|
|
||||||
|
func randomizeUID(pod *corev1.Pod) {
|
||||||
|
pod.ObjectMeta.UID = uuid.NewUUID()
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomizeName(pod *corev1.Pod) {
|
||||||
|
name := fmt.Sprintf("pod-%s", uuid.NewUUID())
|
||||||
|
pod.Name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPod(podmodifiers ...podModifier) *corev1.Pod {
|
||||||
|
pod := &corev1.Pod{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "Pod",
|
Kind: "Pod",
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
@@ -433,4 +477,8 @@ func newPod() *corev1.Pod {
|
|||||||
Phase: corev1.PodPending,
|
Phase: corev1.PodPending,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
for _, modifier := range podmodifiers {
|
||||||
|
modifier(pod)
|
||||||
|
}
|
||||||
|
return pod
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package node
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/virtual-kubelet/virtual-kubelet/errdefs"
|
"github.com/virtual-kubelet/virtual-kubelet/errdefs"
|
||||||
@@ -23,7 +24,7 @@ type mockV0Provider struct {
|
|||||||
|
|
||||||
errorOnDelete error
|
errorOnDelete error
|
||||||
|
|
||||||
pods map[string]*v1.Pod
|
pods sync.Map
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
notifier func(*v1.Pod)
|
notifier func(*v1.Pod)
|
||||||
}
|
}
|
||||||
@@ -35,7 +36,6 @@ type mockProvider struct {
|
|||||||
// NewMockProviderMockConfig creates a new mockV0Provider. Mock legacy provider does not implement the new asynchronous podnotifier interface
|
// NewMockProviderMockConfig creates a new mockV0Provider. Mock legacy provider does not implement the new asynchronous podnotifier interface
|
||||||
func newMockV0Provider() *mockV0Provider {
|
func newMockV0Provider() *mockV0Provider {
|
||||||
provider := mockV0Provider{
|
provider := mockV0Provider{
|
||||||
pods: make(map[string]*v1.Pod),
|
|
||||||
startTime: time.Now(),
|
startTime: time.Now(),
|
||||||
// By default notifier is set to a function which is a no-op. In the event we've implemented the PodNotifier interface,
|
// By default notifier is set to a function which is a no-op. In the event we've implemented the PodNotifier interface,
|
||||||
// it will be set, and then we'll call a real underlying implementation.
|
// it will be set, and then we'll call a real underlying implementation.
|
||||||
@@ -98,7 +98,7 @@ func (p *mockV0Provider) CreatePod(ctx context.Context, pod *v1.Pod) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
p.pods[key] = pod
|
p.pods.Store(key, pod)
|
||||||
p.notifier(pod)
|
p.notifier(pod)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -114,7 +114,7 @@ func (p *mockV0Provider) UpdatePod(ctx context.Context, pod *v1.Pod) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.pods[key] = pod
|
p.pods.Store(key, pod)
|
||||||
p.notifier(pod)
|
p.notifier(pod)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -134,12 +134,12 @@ func (p *mockV0Provider) DeletePod(ctx context.Context, pod *v1.Pod) (err error)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := p.pods[key]; !exists {
|
if _, exists := p.pods.Load(key); !exists {
|
||||||
return errdefs.NotFound("pod not found")
|
return errdefs.NotFound("pod not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
now := metav1.Now()
|
now := metav1.Now()
|
||||||
delete(p.pods, key)
|
p.pods.Delete(key)
|
||||||
pod.Status.Phase = v1.PodSucceeded
|
pod.Status.Phase = v1.PodSucceeded
|
||||||
pod.Status.Reason = "MockProviderPodDeleted"
|
pod.Status.Reason = "MockProviderPodDeleted"
|
||||||
|
|
||||||
@@ -169,8 +169,8 @@ func (p *mockV0Provider) GetPod(ctx context.Context, namespace, name string) (po
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pod, ok := p.pods[key]; ok {
|
if pod, ok := p.pods.Load(key); ok {
|
||||||
return pod, nil
|
return pod.(*v1.Pod), nil
|
||||||
}
|
}
|
||||||
return nil, errdefs.NotFoundf("pod \"%s/%s\" is not known to the provider", namespace, name)
|
return nil, errdefs.NotFoundf("pod \"%s/%s\" is not known to the provider", namespace, name)
|
||||||
}
|
}
|
||||||
@@ -194,9 +194,10 @@ func (p *mockV0Provider) GetPods(ctx context.Context) ([]*v1.Pod, error) {
|
|||||||
|
|
||||||
var pods []*v1.Pod
|
var pods []*v1.Pod
|
||||||
|
|
||||||
for _, pod := range p.pods {
|
p.pods.Range(func(key, pod interface{}) bool {
|
||||||
pods = append(pods, pod)
|
pods = append(pods, pod.(*v1.Pod))
|
||||||
}
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
return pods, nil
|
return pods, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user