From 508ea37bf1ba0120cd77e20a644a232fa50b01f0 Mon Sep 17 00:00:00 2001 From: Carson Ip Date: Tue, 1 Aug 2023 12:17:57 +0100 Subject: [PATCH 1/4] Use vtprotobuf fork; make gen-proto --- aggregationpb/aggregation_vtproto.pb.go | 25 ++++++++++--------------- aggregationpb/labels_vtproto.pb.go | 10 ++++------ tools/go.mod | 2 +- tools/go.sum | 4 ++-- 4 files changed, 17 insertions(+), 24 deletions(-) diff --git a/aggregationpb/aggregation_vtproto.pb.go b/aggregationpb/aggregation_vtproto.pb.go index 70c8565..9b07c6f 100644 --- a/aggregationpb/aggregation_vtproto.pb.go +++ b/aggregationpb/aggregation_vtproto.pb.go @@ -1756,9 +1756,8 @@ var vtprotoPool_CombinedMetrics = sync.Pool{ } func (m *CombinedMetrics) ResetVT() { - for k, mm := range m.ServiceMetrics { - mm.ReturnToVTPool() - m.ServiceMetrics[k] = nil + for _, mm := range m.ServiceMetrics { + mm.ResetVT() } f0 := m.ServiceMetrics[:0] m.OverflowServices.ReturnToVTPool() @@ -1826,9 +1825,8 @@ var vtprotoPool_ServiceMetrics = sync.Pool{ } func (m *ServiceMetrics) ResetVT() { - for k, mm := range m.ServiceInstanceMetrics { - mm.ReturnToVTPool() - m.ServiceInstanceMetrics[k] = nil + for _, mm := range m.ServiceInstanceMetrics { + mm.ResetVT() } f0 := m.ServiceInstanceMetrics[:0] m.OverflowGroups.ReturnToVTPool() @@ -1873,19 +1871,16 @@ var vtprotoPool_ServiceInstanceMetrics = sync.Pool{ } func (m *ServiceInstanceMetrics) ResetVT() { - for k, mm := range m.TransactionMetrics { - mm.ReturnToVTPool() - m.TransactionMetrics[k] = nil + for _, mm := range m.TransactionMetrics { + mm.ResetVT() } f0 := m.TransactionMetrics[:0] - for k, mm := range m.ServiceTransactionMetrics { - mm.ReturnToVTPool() - m.ServiceTransactionMetrics[k] = nil + for _, mm := range m.ServiceTransactionMetrics { + mm.ResetVT() } f1 := m.ServiceTransactionMetrics[:0] - for k, mm := range m.SpanMetrics { - mm.ReturnToVTPool() - m.SpanMetrics[k] = nil + for _, mm := range m.SpanMetrics { + mm.ResetVT() } f2 := m.SpanMetrics[:0] m.Reset() diff --git a/aggregationpb/labels_vtproto.pb.go b/aggregationpb/labels_vtproto.pb.go index fb64476..f437efa 100644 --- a/aggregationpb/labels_vtproto.pb.go +++ b/aggregationpb/labels_vtproto.pb.go @@ -280,14 +280,12 @@ var vtprotoPool_GlobalLabels = sync.Pool{ } func (m *GlobalLabels) ResetVT() { - for k, mm := range m.Labels { - mm.ReturnToVTPool() - m.Labels[k] = nil + for _, mm := range m.Labels { + mm.ResetVT() } f0 := m.Labels[:0] - for k, mm := range m.NumericLabels { - mm.ReturnToVTPool() - m.NumericLabels[k] = nil + for _, mm := range m.NumericLabels { + mm.ResetVT() } f1 := m.NumericLabels[:0] m.Reset() diff --git a/tools/go.mod b/tools/go.mod index 6a73109..bb207ce 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -17,4 +17,4 @@ require ( google.golang.org/protobuf v1.28.1 // indirect ) -replace github.com/planetscale/vtprotobuf => github.com/carsonip/vtprotobuf v0.0.0-20230711135402-2cf3150fde0e +replace github.com/planetscale/vtprotobuf => github.com/grafana/vtprotobuf v0.0.0-20230722075033-e8044ca07485 diff --git a/tools/go.sum b/tools/go.sum index f6417c4..63d37ca 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -1,13 +1,13 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/carsonip/vtprotobuf v0.0.0-20230711135402-2cf3150fde0e h1:lcgWGj99s7E/NzQTsyKtFN+VkHPmYAA8U73Y9fBFZdU= -github.com/carsonip/vtprotobuf v0.0.0-20230711135402-2cf3150fde0e/go.mod h1:wm1N3qk9G/4+VM1WhpkLbvY/d8+0PbwYYpP5P5VhTks= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/elastic/go-licenser v0.4.1 h1:1xDURsc8pL5zYT9R29425J3vkHdt4RT5TNEMeRN48x4= github.com/elastic/go-licenser v0.4.1/go.mod h1:V56wHMpmdURfibNBggaSBfqgPxyT1Tldns1i87iTEvU= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/grafana/vtprotobuf v0.0.0-20230722075033-e8044ca07485 h1:gJYcsZJneV9DVvrcmmvGJLiuM/p+tcJ4cYu9oWvES2s= +github.com/grafana/vtprotobuf v0.0.0-20230722075033-e8044ca07485/go.mod h1:wm1N3qk9G/4+VM1WhpkLbvY/d8+0PbwYYpP5P5VhTks= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= From 3d0649e0c1ebb2b83752c5a2d30c7a6562a3e055 Mon Sep 17 00:00:00 2001 From: Carson Ip Date: Tue, 1 Aug 2023 12:45:51 +0100 Subject: [PATCH 2/4] Fix tests --- aggregators/codec.go | 74 ++++++++++++++++++++++++------------------- aggregators/merger.go | 12 +++---- 2 files changed, 48 insertions(+), 38 deletions(-) diff --git a/aggregators/codec.go b/aggregators/codec.go index 2b1d345..d17bfee 100644 --- a/aggregators/codec.go +++ b/aggregators/codec.go @@ -82,14 +82,17 @@ func (k *CombinedMetricsKey) SizeBinary() int { // ToProto converts CombinedMetrics to its protobuf representation. func (m *combinedMetrics) ToProto() *aggregationpb.CombinedMetrics { pb := aggregationpb.CombinedMetricsFromVTPool() - if len(m.Services) > cap(pb.ServiceMetrics) { - pb.ServiceMetrics = make([]*aggregationpb.KeyedServiceMetrics, 0, len(m.Services)) - } for k, m := range m.Services { - ksm := aggregationpb.KeyedServiceMetricsFromVTPool() - ksm.Key = k.ToProto() - ksm.Metrics = m.ToProto() - pb.ServiceMetrics = append(pb.ServiceMetrics, ksm) + if len(pb.ServiceMetrics) == cap(pb.ServiceMetrics) { + pb.ServiceMetrics = append(pb.ServiceMetrics, &aggregationpb.KeyedServiceMetrics{}) + } else { + pb.ServiceMetrics = pb.ServiceMetrics[:len(pb.ServiceMetrics)+1] + if pb.ServiceMetrics[len(pb.ServiceMetrics)-1] == nil { + pb.ServiceMetrics[len(pb.ServiceMetrics)-1] = &aggregationpb.KeyedServiceMetrics{} + } + } + pb.ServiceMetrics[len(pb.ServiceMetrics)-1].Key = k.ToProto() + pb.ServiceMetrics[len(pb.ServiceMetrics)-1].Metrics = m.ToProto() } if m.OverflowServiceInstancesEstimator != nil { pb.OverflowServices = m.OverflowServices.ToProto() @@ -123,14 +126,17 @@ func (k *serviceAggregationKey) FromProto(pb *aggregationpb.ServiceAggregationKe // ToProto converts ServiceMetrics to its protobuf representation. func (m *serviceMetrics) ToProto() *aggregationpb.ServiceMetrics { pb := aggregationpb.ServiceMetricsFromVTPool() - if len(m.ServiceInstanceGroups) > cap(pb.ServiceInstanceMetrics) { - pb.ServiceInstanceMetrics = make([]*aggregationpb.KeyedServiceInstanceMetrics, 0, len(m.ServiceInstanceGroups)) - } for k, m := range m.ServiceInstanceGroups { - ksim := aggregationpb.KeyedServiceInstanceMetricsFromVTPool() - ksim.Key = k.ToProto() - ksim.Metrics = m.ToProto() - pb.ServiceInstanceMetrics = append(pb.ServiceInstanceMetrics, ksim) + if len(pb.ServiceInstanceMetrics) == cap(pb.ServiceInstanceMetrics) { + pb.ServiceInstanceMetrics = append(pb.ServiceInstanceMetrics, &aggregationpb.KeyedServiceInstanceMetrics{}) + } else { + pb.ServiceInstanceMetrics = pb.ServiceInstanceMetrics[:len(pb.ServiceInstanceMetrics)+1] + if pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1] == nil { + pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1] = &aggregationpb.KeyedServiceInstanceMetrics{} + } + } + pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1].Key = k.ToProto() + pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1].Metrics = m.ToProto() } pb.OverflowGroups = m.OverflowGroups.ToProto() return pb @@ -335,31 +341,35 @@ func (gl *GlobalLabels) ToProto() *aggregationpb.GlobalLabels { // Keys must be sorted to ensure wire formats are deterministically generated and strings are directly comparable // i.e. Protobuf formats are equal if and only if the structs are equal - if len(gl.Labels) > cap(pb.Labels) { - pb.Labels = make([]*aggregationpb.Label, 0, len(gl.Labels)) - } for k, v := range gl.Labels { - l := aggregationpb.LabelFromVTPool() - l.Key = k - l.Value = v.Value - l.Values = v.Values - - pb.Labels = append(pb.Labels, l) + if len(pb.Labels) == cap(pb.Labels) { + pb.Labels = append(pb.Labels, &aggregationpb.Label{}) + } else { + pb.Labels = pb.Labels[:len(pb.Labels)+1] + if pb.Labels[len(pb.Labels)-1] == nil { + pb.Labels[len(pb.Labels)-1] = &aggregationpb.Label{} + } + } + pb.Labels[len(pb.Labels)-1].Key = k + pb.Labels[len(pb.Labels)-1].Value = v.Value + pb.Labels[len(pb.Labels)-1].Values = v.Values } sort.Slice(pb.Labels, func(i, j int) bool { return pb.Labels[i].Key < pb.Labels[j].Key }) - if len(gl.NumericLabels) > cap(pb.NumericLabels) { - pb.NumericLabels = make([]*aggregationpb.NumericLabel, 0, len(gl.NumericLabels)) - } for k, v := range gl.NumericLabels { - l := aggregationpb.NumericLabelFromVTPool() - l.Key = k - l.Value = v.Value - l.Values = v.Values - - pb.NumericLabels = append(pb.NumericLabels, l) + if len(pb.NumericLabels) == cap(pb.NumericLabels) { + pb.NumericLabels = append(pb.NumericLabels, &aggregationpb.NumericLabel{}) + } else { + pb.NumericLabels = pb.NumericLabels[:len(pb.NumericLabels)+1] + if pb.NumericLabels[len(pb.NumericLabels)-1] == nil { + pb.NumericLabels[len(pb.NumericLabels)-1] = &aggregationpb.NumericLabel{} + } + } + pb.NumericLabels[len(pb.NumericLabels)-1].Key = k + pb.NumericLabels[len(pb.NumericLabels)-1].Value = v.Value + pb.NumericLabels[len(pb.NumericLabels)-1].Values = v.Values } sort.Slice(pb.NumericLabels, func(i, j int) bool { return pb.NumericLabels[i].Key < pb.NumericLabels[j].Key diff --git a/aggregators/merger.go b/aggregators/merger.go index 4075211..5b89aa1 100644 --- a/aggregators/merger.go +++ b/aggregators/merger.go @@ -215,8 +215,8 @@ func mergeTransactionGroups( perSvcConstraint.add(1) globalConstraint.add(1) - to[tk] = fromTxn - from[i] = nil + to[tk] = fromTxn.CloneVT() + //from[i] = nil continue } mergeKeyedTransactionMetrics(toTxn, fromTxn) @@ -250,8 +250,8 @@ func mergeServiceTransactionGroups( perSvcConstraint.add(1) globalConstraint.add(1) - to[stk] = fromSvcTxn - from[i] = nil + to[stk] = fromSvcTxn.CloneVT() + //from[i] = nil continue } mergeKeyedServiceTransactionMetrics(toSvcTxn, fromSvcTxn) @@ -293,8 +293,8 @@ func mergeSpanGroups( perSvcConstraint.add(1) globalConstraint.add(1) - to[spk] = fromSpan - from[i] = nil + to[spk] = fromSpan.CloneVT() + //from[i] = nil continue } } From c993451d57f7aded908d79910ed27eee79efe1ad Mon Sep 17 00:00:00 2001 From: Carson Ip Date: Tue, 1 Aug 2023 13:04:53 +0100 Subject: [PATCH 3/4] Use slices.Grow --- aggregators/codec.go | 61 +++++++++++++++++-------------------------- aggregators/merger.go | 3 --- 2 files changed, 24 insertions(+), 40 deletions(-) diff --git a/aggregators/codec.go b/aggregators/codec.go index d17bfee..cd10e80 100644 --- a/aggregators/codec.go +++ b/aggregators/codec.go @@ -14,6 +14,7 @@ import ( "time" "github.com/axiomhq/hyperloglog" + "golang.org/x/exp/slices" "github.com/elastic/apm-aggregation/aggregationpb" "github.com/elastic/apm-aggregation/aggregators/internal/hdrhistogram" @@ -82,14 +83,11 @@ func (k *CombinedMetricsKey) SizeBinary() int { // ToProto converts CombinedMetrics to its protobuf representation. func (m *combinedMetrics) ToProto() *aggregationpb.CombinedMetrics { pb := aggregationpb.CombinedMetricsFromVTPool() + pb.ServiceMetrics = slices.Grow(pb.ServiceMetrics, len(m.Services)) for k, m := range m.Services { - if len(pb.ServiceMetrics) == cap(pb.ServiceMetrics) { - pb.ServiceMetrics = append(pb.ServiceMetrics, &aggregationpb.KeyedServiceMetrics{}) - } else { - pb.ServiceMetrics = pb.ServiceMetrics[:len(pb.ServiceMetrics)+1] - if pb.ServiceMetrics[len(pb.ServiceMetrics)-1] == nil { - pb.ServiceMetrics[len(pb.ServiceMetrics)-1] = &aggregationpb.KeyedServiceMetrics{} - } + pb.ServiceMetrics = pb.ServiceMetrics[:len(pb.ServiceMetrics)+1] + if pb.ServiceMetrics[len(pb.ServiceMetrics)-1] == nil { + pb.ServiceMetrics[len(pb.ServiceMetrics)-1] = &aggregationpb.KeyedServiceMetrics{} } pb.ServiceMetrics[len(pb.ServiceMetrics)-1].Key = k.ToProto() pb.ServiceMetrics[len(pb.ServiceMetrics)-1].Metrics = m.ToProto() @@ -126,14 +124,11 @@ func (k *serviceAggregationKey) FromProto(pb *aggregationpb.ServiceAggregationKe // ToProto converts ServiceMetrics to its protobuf representation. func (m *serviceMetrics) ToProto() *aggregationpb.ServiceMetrics { pb := aggregationpb.ServiceMetricsFromVTPool() + pb.ServiceInstanceMetrics = slices.Grow(pb.ServiceInstanceMetrics, len(m.ServiceInstanceGroups)) for k, m := range m.ServiceInstanceGroups { - if len(pb.ServiceInstanceMetrics) == cap(pb.ServiceInstanceMetrics) { - pb.ServiceInstanceMetrics = append(pb.ServiceInstanceMetrics, &aggregationpb.KeyedServiceInstanceMetrics{}) - } else { - pb.ServiceInstanceMetrics = pb.ServiceInstanceMetrics[:len(pb.ServiceInstanceMetrics)+1] - if pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1] == nil { - pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1] = &aggregationpb.KeyedServiceInstanceMetrics{} - } + pb.ServiceInstanceMetrics = pb.ServiceInstanceMetrics[:len(pb.ServiceInstanceMetrics)+1] + if pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1] == nil { + pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1] = &aggregationpb.KeyedServiceInstanceMetrics{} } pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1].Key = k.ToProto() pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1].Metrics = m.ToProto() @@ -157,24 +152,22 @@ func (k *serviceInstanceAggregationKey) FromProto(pb *aggregationpb.ServiceInsta // ToProto converts ServiceInstanceMetrics to its protobuf representation. func (m *serviceInstanceMetrics) ToProto() *aggregationpb.ServiceInstanceMetrics { pb := aggregationpb.ServiceInstanceMetricsFromVTPool() - if len(m.TransactionGroups) > cap(pb.TransactionMetrics) { - pb.TransactionMetrics = make([]*aggregationpb.KeyedTransactionMetrics, 0, len(m.TransactionGroups)) - } + + pb.TransactionMetrics = slices.Grow(pb.TransactionMetrics, len(m.TransactionGroups)) for _, m := range m.TransactionGroups { pb.TransactionMetrics = append(pb.TransactionMetrics, m) } - if len(m.ServiceTransactionGroups) > cap(pb.ServiceTransactionMetrics) { - pb.ServiceTransactionMetrics = make([]*aggregationpb.KeyedServiceTransactionMetrics, 0, len(m.ServiceTransactionGroups)) - } + + pb.ServiceTransactionMetrics = slices.Grow(pb.ServiceTransactionMetrics, len(m.ServiceTransactionGroups)) for _, m := range m.ServiceTransactionGroups { pb.ServiceTransactionMetrics = append(pb.ServiceTransactionMetrics, m) } - if len(m.SpanGroups) > cap(pb.SpanMetrics) { - pb.SpanMetrics = make([]*aggregationpb.KeyedSpanMetrics, 0, len(m.SpanGroups)) - } + + pb.SpanMetrics = slices.Grow(pb.SpanMetrics, len(m.SpanGroups)) for _, m := range m.SpanGroups { pb.SpanMetrics = append(pb.SpanMetrics, m) } + return pb } @@ -341,14 +334,11 @@ func (gl *GlobalLabels) ToProto() *aggregationpb.GlobalLabels { // Keys must be sorted to ensure wire formats are deterministically generated and strings are directly comparable // i.e. Protobuf formats are equal if and only if the structs are equal + pb.Labels = slices.Grow(pb.Labels, len(gl.Labels)) for k, v := range gl.Labels { - if len(pb.Labels) == cap(pb.Labels) { - pb.Labels = append(pb.Labels, &aggregationpb.Label{}) - } else { - pb.Labels = pb.Labels[:len(pb.Labels)+1] - if pb.Labels[len(pb.Labels)-1] == nil { - pb.Labels[len(pb.Labels)-1] = &aggregationpb.Label{} - } + pb.Labels = pb.Labels[:len(pb.Labels)+1] + if pb.Labels[len(pb.Labels)-1] == nil { + pb.Labels[len(pb.Labels)-1] = &aggregationpb.Label{} } pb.Labels[len(pb.Labels)-1].Key = k pb.Labels[len(pb.Labels)-1].Value = v.Value @@ -358,14 +348,11 @@ func (gl *GlobalLabels) ToProto() *aggregationpb.GlobalLabels { return pb.Labels[i].Key < pb.Labels[j].Key }) + pb.NumericLabels = slices.Grow(pb.NumericLabels, len(gl.NumericLabels)) for k, v := range gl.NumericLabels { - if len(pb.NumericLabels) == cap(pb.NumericLabels) { - pb.NumericLabels = append(pb.NumericLabels, &aggregationpb.NumericLabel{}) - } else { - pb.NumericLabels = pb.NumericLabels[:len(pb.NumericLabels)+1] - if pb.NumericLabels[len(pb.NumericLabels)-1] == nil { - pb.NumericLabels[len(pb.NumericLabels)-1] = &aggregationpb.NumericLabel{} - } + pb.NumericLabels = pb.NumericLabels[:len(pb.NumericLabels)+1] + if pb.NumericLabels[len(pb.NumericLabels)-1] == nil { + pb.NumericLabels[len(pb.NumericLabels)-1] = &aggregationpb.NumericLabel{} } pb.NumericLabels[len(pb.NumericLabels)-1].Key = k pb.NumericLabels[len(pb.NumericLabels)-1].Value = v.Value diff --git a/aggregators/merger.go b/aggregators/merger.go index 5b89aa1..96e71f9 100644 --- a/aggregators/merger.go +++ b/aggregators/merger.go @@ -216,7 +216,6 @@ func mergeTransactionGroups( globalConstraint.add(1) to[tk] = fromTxn.CloneVT() - //from[i] = nil continue } mergeKeyedTransactionMetrics(toTxn, fromTxn) @@ -251,7 +250,6 @@ func mergeServiceTransactionGroups( globalConstraint.add(1) to[stk] = fromSvcTxn.CloneVT() - //from[i] = nil continue } mergeKeyedServiceTransactionMetrics(toSvcTxn, fromSvcTxn) @@ -294,7 +292,6 @@ func mergeSpanGroups( globalConstraint.add(1) to[spk] = fromSpan.CloneVT() - //from[i] = nil continue } } From 41ddd426156a912dfb9323f3966f8403de950862 Mon Sep 17 00:00:00 2001 From: Carson Ip Date: Wed, 2 Aug 2023 11:10:37 +0100 Subject: [PATCH 4/4] Tidy up reslicing --- aggregators/codec.go | 56 ++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/aggregators/codec.go b/aggregators/codec.go index cd10e80..4659bfe 100644 --- a/aggregators/codec.go +++ b/aggregators/codec.go @@ -83,14 +83,15 @@ func (k *CombinedMetricsKey) SizeBinary() int { // ToProto converts CombinedMetrics to its protobuf representation. func (m *combinedMetrics) ToProto() *aggregationpb.CombinedMetrics { pb := aggregationpb.CombinedMetricsFromVTPool() - pb.ServiceMetrics = slices.Grow(pb.ServiceMetrics, len(m.Services)) + pb.ServiceMetrics = slices.Grow(pb.ServiceMetrics, len(m.Services))[:len(m.Services)] + var i int for k, m := range m.Services { - pb.ServiceMetrics = pb.ServiceMetrics[:len(pb.ServiceMetrics)+1] - if pb.ServiceMetrics[len(pb.ServiceMetrics)-1] == nil { - pb.ServiceMetrics[len(pb.ServiceMetrics)-1] = &aggregationpb.KeyedServiceMetrics{} + if pb.ServiceMetrics[i] == nil { + pb.ServiceMetrics[i] = &aggregationpb.KeyedServiceMetrics{} } - pb.ServiceMetrics[len(pb.ServiceMetrics)-1].Key = k.ToProto() - pb.ServiceMetrics[len(pb.ServiceMetrics)-1].Metrics = m.ToProto() + pb.ServiceMetrics[i].Key = k.ToProto() + pb.ServiceMetrics[i].Metrics = m.ToProto() + i++ } if m.OverflowServiceInstancesEstimator != nil { pb.OverflowServices = m.OverflowServices.ToProto() @@ -124,14 +125,15 @@ func (k *serviceAggregationKey) FromProto(pb *aggregationpb.ServiceAggregationKe // ToProto converts ServiceMetrics to its protobuf representation. func (m *serviceMetrics) ToProto() *aggregationpb.ServiceMetrics { pb := aggregationpb.ServiceMetricsFromVTPool() - pb.ServiceInstanceMetrics = slices.Grow(pb.ServiceInstanceMetrics, len(m.ServiceInstanceGroups)) + pb.ServiceInstanceMetrics = slices.Grow(pb.ServiceInstanceMetrics, len(m.ServiceInstanceGroups))[:len(m.ServiceInstanceGroups)] + var i int for k, m := range m.ServiceInstanceGroups { - pb.ServiceInstanceMetrics = pb.ServiceInstanceMetrics[:len(pb.ServiceInstanceMetrics)+1] - if pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1] == nil { - pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1] = &aggregationpb.KeyedServiceInstanceMetrics{} + if pb.ServiceInstanceMetrics[i] == nil { + pb.ServiceInstanceMetrics[i] = &aggregationpb.KeyedServiceInstanceMetrics{} } - pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1].Key = k.ToProto() - pb.ServiceInstanceMetrics[len(pb.ServiceInstanceMetrics)-1].Metrics = m.ToProto() + pb.ServiceInstanceMetrics[i].Key = k.ToProto() + pb.ServiceInstanceMetrics[i].Metrics = m.ToProto() + i++ } pb.OverflowGroups = m.OverflowGroups.ToProto() return pb @@ -334,29 +336,31 @@ func (gl *GlobalLabels) ToProto() *aggregationpb.GlobalLabels { // Keys must be sorted to ensure wire formats are deterministically generated and strings are directly comparable // i.e. Protobuf formats are equal if and only if the structs are equal - pb.Labels = slices.Grow(pb.Labels, len(gl.Labels)) + pb.Labels = slices.Grow(pb.Labels, len(gl.Labels))[:len(gl.Labels)] + var i int for k, v := range gl.Labels { - pb.Labels = pb.Labels[:len(pb.Labels)+1] - if pb.Labels[len(pb.Labels)-1] == nil { - pb.Labels[len(pb.Labels)-1] = &aggregationpb.Label{} + if pb.Labels[i] == nil { + pb.Labels[i] = &aggregationpb.Label{} } - pb.Labels[len(pb.Labels)-1].Key = k - pb.Labels[len(pb.Labels)-1].Value = v.Value - pb.Labels[len(pb.Labels)-1].Values = v.Values + pb.Labels[i].Key = k + pb.Labels[i].Value = v.Value + pb.Labels[i].Values = v.Values + i++ } sort.Slice(pb.Labels, func(i, j int) bool { return pb.Labels[i].Key < pb.Labels[j].Key }) - pb.NumericLabels = slices.Grow(pb.NumericLabels, len(gl.NumericLabels)) + pb.NumericLabels = slices.Grow(pb.NumericLabels, len(gl.NumericLabels))[:len(gl.NumericLabels)] + i = 0 for k, v := range gl.NumericLabels { - pb.NumericLabels = pb.NumericLabels[:len(pb.NumericLabels)+1] - if pb.NumericLabels[len(pb.NumericLabels)-1] == nil { - pb.NumericLabels[len(pb.NumericLabels)-1] = &aggregationpb.NumericLabel{} + if pb.NumericLabels[i] == nil { + pb.NumericLabels[i] = &aggregationpb.NumericLabel{} } - pb.NumericLabels[len(pb.NumericLabels)-1].Key = k - pb.NumericLabels[len(pb.NumericLabels)-1].Value = v.Value - pb.NumericLabels[len(pb.NumericLabels)-1].Values = v.Values + pb.NumericLabels[i].Key = k + pb.NumericLabels[i].Value = v.Value + pb.NumericLabels[i].Values = v.Values + i++ } sort.Slice(pb.NumericLabels, func(i, j int) bool { return pb.NumericLabels[i].Key < pb.NumericLabels[j].Key