Skip to content

Commit d78929e

Browse files
authored
fix(cluster): reduce lock contention on cluster initialization (#660)
* fix: move expensive function outside lock Signed-off-by: Michael Crenshaw <[email protected]> * add benchmark Signed-off-by: Michael Crenshaw <[email protected]> --------- Signed-off-by: Michael Crenshaw <[email protected]>
1 parent 54992bf commit d78929e

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

pkg/cache/cluster.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -939,8 +939,9 @@ func (c *clusterCache) sync() error {
939939
if un, ok := obj.(*unstructured.Unstructured); !ok {
940940
return fmt.Errorf("object %s/%s has an unexpected type", un.GroupVersionKind().String(), un.GetName())
941941
} else {
942+
newRes := c.newResource(un)
942943
lock.Lock()
943-
c.setNode(c.newResource(un))
944+
c.setNode(newRes)
944945
lock.Unlock()
945946
}
946947
return nil

pkg/cache/cluster_test.go

+42
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,48 @@ func getChildren(cluster *clusterCache, un *unstructured.Unstructured) []*Resour
146146
return hierarchy[1:]
147147
}
148148

149+
// Benchmark_sync is meant to simulate cluster initialization when populateResourceInfoHandler does nontrivial work.
150+
func Benchmark_sync(t *testing.B) {
151+
var resources = []runtime.Object{}
152+
for i := 0; i < 100; i++ {
153+
resources = append(resources, &corev1.Pod{
154+
ObjectMeta: metav1.ObjectMeta{
155+
Name: fmt.Sprintf("pod-%d", i),
156+
Namespace: "default",
157+
},
158+
}, &appsv1.ReplicaSet{
159+
ObjectMeta: metav1.ObjectMeta{
160+
Name: fmt.Sprintf("rs-%d", i),
161+
Namespace: "default",
162+
},
163+
}, &appsv1.Deployment{
164+
ObjectMeta: metav1.ObjectMeta{
165+
Name: fmt.Sprintf("deploy-%d", i),
166+
Namespace: "default",
167+
},
168+
}, &appsv1.StatefulSet{
169+
ObjectMeta: metav1.ObjectMeta{
170+
Name: fmt.Sprintf("sts-%d", i),
171+
Namespace: "default",
172+
},
173+
})
174+
}
175+
176+
c := newCluster(t, resources...)
177+
178+
c.populateResourceInfoHandler = func(un *unstructured.Unstructured, isRoot bool) (info interface{}, cacheManifest bool) {
179+
time.Sleep(10 * time.Microsecond)
180+
return nil, false
181+
}
182+
183+
t.ResetTimer()
184+
185+
for n := 0; n < t.N; n++ {
186+
err := c.sync()
187+
require.NoError(t, err)
188+
}
189+
}
190+
149191
func TestEnsureSynced(t *testing.T) {
150192
obj1 := &appsv1.Deployment{
151193
TypeMeta: metav1.TypeMeta{

0 commit comments

Comments
 (0)