diff --git a/discovery/kubernetes/endpoints.go b/discovery/kubernetes/endpoints.go index 5ba9df6276..934f37ee45 100644 --- a/discovery/kubernetes/endpoints.go +++ b/discovery/kubernetes/endpoints.go @@ -20,6 +20,8 @@ import ( "log/slog" "net" "strconv" + "strings" + "sync" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" @@ -453,15 +455,43 @@ func (e *Endpoints) buildEndpoints(eps *apiv1.Endpoints) *targetgroup.Group { return tg } +var objKeyPool = sync.Pool{} + +func generateObjKey(namespace, name string) (string, *strings.Builder) { + var sb *strings.Builder + + b := objKeyPool.Get() + if b == nil { + sb = &strings.Builder{} + } else { + sb = b.(*strings.Builder) + } + + sb.Reset() + if namespace == "" { + _, _ = sb.WriteString(name) + return sb.String(), sb + } + + _, _ = sb.WriteString(namespace) + _, _ = sb.WriteRune('/') + _, _ = sb.WriteString(name) + return sb.String(), sb +} + func (e *Endpoints) resolvePodRef(ref *apiv1.ObjectReference) *apiv1.Pod { if ref == nil || ref.Kind != "Pod" { return nil } + p := &apiv1.Pod{} p.Namespace = ref.Namespace p.Name = ref.Name - obj, exists, err := e.podStore.Get(p) + key, sb := generateObjKey(p.Namespace, p.Name) + defer objKeyPool.Put(sb) + + obj, exists, err := e.podStore.GetByKey(key) if err != nil { e.logger.Error("resolving pod ref failed", "err", err) return nil diff --git a/discovery/kubernetes/endpoints_test.go b/discovery/kubernetes/endpoints_test.go index 4af6889602..a1ac6e5d48 100644 --- a/discovery/kubernetes/endpoints_test.go +++ b/discovery/kubernetes/endpoints_test.go @@ -18,10 +18,12 @@ import ( "testing" "github.com/prometheus/common/model" + "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/cache" "github.com/prometheus/prometheus/discovery/targetgroup" ) @@ -1257,3 +1259,22 @@ func TestEndpointsDiscoverySidecarContainer(t *testing.T) { }, }.Run(t) } + +func BenchmarkResolvePodRef(b *testing.B) { + indexer := cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, nil) + e := &Endpoints{ + podStore: indexer, + } + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + p := e.resolvePodRef(&v1.ObjectReference{ + Kind: "Pod", + Name: "testpod", + Namespace: "foo", + }) + require.Nil(b, p) + } +}