From e800298893cd19103b3d0ca7316592e7d5caad75 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Wed, 22 May 2024 07:34:51 -0700 Subject: [PATCH] Pool otlploghttp transform maps (#5378) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of #5196 ### Benchmarks ```console goos: linux goarch: amd64 pkg: go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp/internal/transform cpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ ResourceLogs-8 6.033µ ± 4% 5.249µ ± 8% -13.00% (p=0.000 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ ResourceLogs-8 10.602Ki ± 0% 8.299Ki ± 0% -21.72% (p=0.000 n=10) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ ResourceLogs-8 188.0 ± 0% 178.0 ± 0% -5.32% (p=0.000 n=10) ``` --- .../otlploghttp/internal/transform/log.go | 45 ++++++++++++++----- .../internal/transform/log_test.go | 11 +++++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/exporters/otlp/otlplog/otlploghttp/internal/transform/log.go b/exporters/otlp/otlplog/otlploghttp/internal/transform/log.go index a59536aa704..b1d33a80cce 100644 --- a/exporters/otlp/otlplog/otlploghttp/internal/transform/log.go +++ b/exporters/otlp/otlplog/otlploghttp/internal/transform/log.go @@ -6,6 +6,7 @@ package transform // import "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp/internal/transform" import ( + "sync" "time" cpb "go.opentelemetry.io/proto/otlp/common/v1" @@ -24,7 +25,13 @@ func ResourceLogs(records []log.Record) []*lpb.ResourceLogs { return nil } - resMap := resourceLogsMap(records) + resMap := resourceLogsMapPool.Get().(map[attribute.Distinct]*lpb.ResourceLogs) + defer func() { + clear(resMap) + resourceLogsMapPool.Put(resMap) + }() + resourceLogsMap(&resMap, records) + out := make([]*lpb.ResourceLogs, 0, len(resMap)) for _, rl := range resMap { out = append(out, rl) @@ -32,11 +39,16 @@ func ResourceLogs(records []log.Record) []*lpb.ResourceLogs { return out } -func resourceLogsMap(records []log.Record) map[attribute.Distinct]*lpb.ResourceLogs { - out := make(map[attribute.Distinct]*lpb.ResourceLogs) +var resourceLogsMapPool = sync.Pool{ + New: func() any { + return make(map[attribute.Distinct]*lpb.ResourceLogs) + }, +} + +func resourceLogsMap(dst *map[attribute.Distinct]*lpb.ResourceLogs, records []log.Record) { for _, r := range records { res := r.Resource() - rl, ok := out[res.Equivalent()] + rl, ok := (*dst)[res.Equivalent()] if !ok { rl = new(lpb.ResourceLogs) if res.Len() > 0 { @@ -45,16 +57,21 @@ func resourceLogsMap(records []log.Record) map[attribute.Distinct]*lpb.ResourceL } } rl.SchemaUrl = res.SchemaURL() - out[res.Equivalent()] = rl + (*dst)[res.Equivalent()] = rl } rl.ScopeLogs = ScopeLogs(records) } - return out } // ScopeLogs returns a slice of OTLP ScopeLogs generated from recoreds. func ScopeLogs(records []log.Record) []*lpb.ScopeLogs { - scopeMap := scopeLogsMap(records) + scopeMap := scopeLogsMapPool.Get().(map[instrumentation.Scope]*lpb.ScopeLogs) + defer func() { + clear(scopeMap) + scopeLogsMapPool.Put(scopeMap) + }() + scopeLogsMap(&scopeMap, records) + out := make([]*lpb.ScopeLogs, 0, len(scopeMap)) for _, sl := range scopeMap { out = append(out, sl) @@ -62,11 +79,16 @@ func ScopeLogs(records []log.Record) []*lpb.ScopeLogs { return out } -func scopeLogsMap(records []log.Record) map[instrumentation.Scope]*lpb.ScopeLogs { - out := make(map[instrumentation.Scope]*lpb.ScopeLogs) +var scopeLogsMapPool = sync.Pool{ + New: func() any { + return make(map[instrumentation.Scope]*lpb.ScopeLogs) + }, +} + +func scopeLogsMap(dst *map[instrumentation.Scope]*lpb.ScopeLogs, records []log.Record) { for _, r := range records { scope := r.InstrumentationScope() - sl, ok := out[scope] + sl, ok := (*dst)[scope] if !ok { sl = new(lpb.ScopeLogs) var emptyScope instrumentation.Scope @@ -77,11 +99,10 @@ func scopeLogsMap(records []log.Record) map[instrumentation.Scope]*lpb.ScopeLogs } sl.SchemaUrl = scope.SchemaURL } - out[scope] = sl + (*dst)[scope] = sl } sl.LogRecords = append(sl.LogRecords, LogRecord(r)) } - return out } // LogRecord returns an OTLP LogRecord generated from record. diff --git a/exporters/otlp/otlplog/otlploghttp/internal/transform/log_test.go b/exporters/otlp/otlplog/otlploghttp/internal/transform/log_test.go index 73368b9701a..acb9c3223b1 100644 --- a/exporters/otlp/otlplog/otlploghttp/internal/transform/log_test.go +++ b/exporters/otlp/otlplog/otlploghttp/internal/transform/log_test.go @@ -230,3 +230,14 @@ func TestSeverityNumber(t *testing.T) { assert.Equal(t, want, SeverityNumber(api.Severity(i))) } } + +func BenchmarkResourceLogs(b *testing.B) { + b.ReportAllocs() + b.RunParallel(func(pb *testing.PB) { + var out []*lpb.ResourceLogs + for pb.Next() { + out = ResourceLogs(records) + } + _ = out + }) +}