diff --git a/pilot/pkg/model/push_context.go b/pilot/pkg/model/push_context.go index 45f92fab03f4..f5e92a08dee5 100644 --- a/pilot/pkg/model/push_context.go +++ b/pilot/pkg/model/push_context.go @@ -354,6 +354,7 @@ type PushRequest struct { type TriggerReason string +// If adding a new reason, update xds/monitoring.go:triggerMetric const ( // EndpointUpdate describes a push triggered by an Endpoint change EndpointUpdate TriggerReason = "endpoint" diff --git a/pilot/pkg/xds/bench_test.go b/pilot/pkg/xds/bench_test.go index be2f81a3dff6..22f280b11c11 100644 --- a/pilot/pkg/xds/bench_test.go +++ b/pilot/pkg/xds/bench_test.go @@ -502,3 +502,45 @@ func createEndpoints(numEndpoints, numServices, numNetworks int) []config.Config } return result } + +func BenchmarkPushRequest(b *testing.B) { + // allTriggers contains all triggers, so we can pick one at random. + // It is not a big issue if it falls out of sync, as we are just trying to generate test data + allTriggers := []model.TriggerReason{ + model.EndpointUpdate, + model.ConfigUpdate, + model.ServiceUpdate, + model.ProxyUpdate, + model.GlobalUpdate, + model.UnknownTrigger, + model.DebugTrigger, + model.SecretTrigger, + model.NetworksTrigger, + model.ProxyRequest, + model.NamespaceUpdate, + } + // Number of (simulated) proxies + proxies := 500 + // Number of (simulated) pushes merged + pushesMerged := 10 + // Number of configs per push + configs := 1 + + for n := 0; n < b.N; n++ { + var req *model.PushRequest + for i := 0; i < pushesMerged; i++ { + trigger := allTriggers[i%len(allTriggers)] + nreq := &model.PushRequest{ + ConfigsUpdated: map[model.ConfigKey]struct{}{}, + Reason: []model.TriggerReason{trigger}, + } + for c := 0; c < configs; c++ { + nreq.ConfigsUpdated[model.ConfigKey{Kind: gvk.ServiceEntry, Name: fmt.Sprintf("%d", c), Namespace: "default"}] = struct{}{} + } + req = req.Merge(nreq) + } + for p := 0; p < proxies; p++ { + recordPushTriggers(req.Reason...) + } + } +} diff --git a/pilot/pkg/xds/monitoring.go b/pilot/pkg/xds/monitoring.go index e7eeabfb0a6a..bbc572897349 100644 --- a/pilot/pkg/xds/monitoring.go +++ b/pilot/pkg/xds/monitoring.go @@ -202,9 +202,29 @@ func recordXDSClients(version string, delta float64) { xdsClients.With(versionTag.Value(version)).Record(xdsClientTracker[version]) } +// triggerMetric is a precomputed monitoring.Metric for each trigger type. This saves on a lot of allocations +var triggerMetric = map[model.TriggerReason]monitoring.Metric{ + model.EndpointUpdate: pushTriggers.With(typeTag.Value(string(model.EndpointUpdate))), + model.ConfigUpdate: pushTriggers.With(typeTag.Value(string(model.ConfigUpdate))), + model.ServiceUpdate: pushTriggers.With(typeTag.Value(string(model.ServiceUpdate))), + model.ProxyUpdate: pushTriggers.With(typeTag.Value(string(model.ProxyUpdate))), + model.GlobalUpdate: pushTriggers.With(typeTag.Value(string(model.GlobalUpdate))), + model.UnknownTrigger: pushTriggers.With(typeTag.Value(string(model.UnknownTrigger))), + model.DebugTrigger: pushTriggers.With(typeTag.Value(string(model.DebugTrigger))), + model.SecretTrigger: pushTriggers.With(typeTag.Value(string(model.SecretTrigger))), + model.NetworksTrigger: pushTriggers.With(typeTag.Value(string(model.NetworksTrigger))), + model.ProxyRequest: pushTriggers.With(typeTag.Value(string(model.ProxyRequest))), + model.NamespaceUpdate: pushTriggers.With(typeTag.Value(string(model.NamespaceUpdate))), +} + func recordPushTriggers(reasons ...model.TriggerReason) { for _, r := range reasons { - pushTriggers.With(typeTag.Value(string(r))).Increment() + t, f := triggerMetric[r] + if f { + t.Increment() + } else { + pushTriggers.With(typeTag.Value(string(r))).Increment() + } } }