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:
Sargun Dhillon
2019-07-27 12:43:39 -07:00
parent ce38d72c0e
commit bd8e39e3f9
4 changed files with 67 additions and 13 deletions

View File

@@ -15,6 +15,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apimachinery/pkg/watch"
kubeinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
@@ -414,8 +415,51 @@ func testCreateStartDeleteScenario(ctx context.Context, t *testing.T, s *system)
}
}
func newPod() *corev1.Pod {
return &corev1.Pod{
func BenchmarkCreatePods(b *testing.B) {
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{
Kind: "Pod",
APIVersion: "v1",
@@ -433,4 +477,8 @@ func newPod() *corev1.Pod {
Phase: corev1.PodPending,
},
}
for _, modifier := range podmodifiers {
modifier(pod)
}
return pod
}

View File

@@ -3,6 +3,7 @@ package node
import (
"context"
"fmt"
"sync"
"time"
"github.com/virtual-kubelet/virtual-kubelet/errdefs"
@@ -23,7 +24,7 @@ type mockV0Provider struct {
errorOnDelete error
pods map[string]*v1.Pod
pods sync.Map
startTime time.Time
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
func newMockV0Provider() *mockV0Provider {
provider := mockV0Provider{
pods: make(map[string]*v1.Pod),
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,
// 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)
return nil
@@ -114,7 +114,7 @@ func (p *mockV0Provider) UpdatePod(ctx context.Context, pod *v1.Pod) error {
return err
}
p.pods[key] = pod
p.pods.Store(key, pod)
p.notifier(pod)
return nil
@@ -134,12 +134,12 @@ func (p *mockV0Provider) DeletePod(ctx context.Context, pod *v1.Pod) (err error)
return err
}
if _, exists := p.pods[key]; !exists {
if _, exists := p.pods.Load(key); !exists {
return errdefs.NotFound("pod not found")
}
now := metav1.Now()
delete(p.pods, key)
p.pods.Delete(key)
pod.Status.Phase = v1.PodSucceeded
pod.Status.Reason = "MockProviderPodDeleted"
@@ -169,8 +169,8 @@ func (p *mockV0Provider) GetPod(ctx context.Context, namespace, name string) (po
return nil, err
}
if pod, ok := p.pods[key]; ok {
return pod, nil
if pod, ok := p.pods.Load(key); ok {
return pod.(*v1.Pod), nil
}
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
for _, pod := range p.pods {
pods = append(pods, pod)
}
p.pods.Range(func(key, pod interface{}) bool {
pods = append(pods, pod.(*v1.Pod))
return true
})
return pods, nil
}