You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-11-23 22:34:47 +02:00
With specialized routines, we can avoid the allocation of hex.DecodeString since we know the structure of the IDs. We can use `==` instead of bytes.Equal for arrays. From the Go [spec]: > Array types are comparable if their array element types are comparable. Two > array values are equal if their corresponding element values are equal. The > elements are compared in ascending index order, and comparison stops as soon > as two element values differ (or all elements have been compared). [spec]: https://go.dev/ref/spec#Comparison_operators ### Benchstat To generate: ```sh mkdir private cd sdk go test -run=xxxxMatchNothingxxxx -bench=. -count=10 go.opentelemetry.io/otel/sdk/trace -timeout=30m | tee ../private/base.txt go test -run=xxxxMatchNothingxxxx -bench=. -count=10 go.opentelemetry.io/otel/sdk/trace -timeout=30m | tee ../private/new.txt benchstat ../private/base.txt ../private/new.txt ``` ### Results as of 2025-08-21 ``` goos: darwin goarch: arm64 pkg: go.opentelemetry.io/otel/sdk/trace cpu: Apple M2 Max │ ../private/base.txt │ ../private/new.txt │ │ sec/op │ sec/op vs base │ Truncate/Unlimited-12 0.2274n ± 2% 0.2262n ± 1% ~ (p=0.971 n=10) Truncate/Zero-12 0.3252n ± 1% 0.3267n ± 1% ~ (p=0.171 n=10) Truncate/Short-12 0.2250n ± 1% 0.2247n ± 1% ~ (p=0.897 n=10) Truncate/ASCII-12 0.7280n ± 0% 0.7297n ± 0% ~ (p=0.159 n=10) Truncate/ValidUTF-8-12 1.373n ± 3% 1.376n ± 9% ~ (p=0.084 n=10) Truncate/InvalidUTF-8-12 9.605n ± 4% 9.724n ± 7% ~ (p=0.289 n=10) Truncate/MixedUTF-8-12 17.54n ± 2% 17.56n ± 1% ~ (p=0.839 n=10) RecordingSpanSetAttributes/WithLimit/false-12 2.046µ ± 1% 2.055µ ± 1% ~ (p=0.383 n=10) RecordingSpanSetAttributes/WithLimit/true-12 4.329µ ± 0% 4.335µ ± 0% ~ (p=0.108 n=10) SpanEnd-12 90.10n ± 30% 102.26n ± 20% ~ (p=0.143 n=10) TraceStart/with_a_simple_span-12 300.4n ± 7% 290.1n ± 4% ~ (p=0.353 n=10) TraceStart/with_several_links-12 416.8n ± 3% 407.0n ± 2% -2.34% (p=0.014 n=10) TraceStart/with_attributes-12 460.6n ± 1% 446.5n ± 2% -3.04% (p=0.000 n=10) SpanLimits/AttributeValueLengthLimit-12 4.425µ ± 3% 4.254µ ± 1% -3.86% (p=0.000 n=10) SpanLimits/AttributeCountLimit-12 4.138µ ± 1% 3.986µ ± 1% -3.65% (p=0.000 n=10) SpanLimits/EventCountLimit-12 3.926µ ± 1% 3.780µ ± 1% -3.73% (p=0.000 n=10) SpanLimits/LinkCountLimit-12 3.879µ ± 1% 3.738µ ± 1% -3.64% (p=0.000 n=10) SpanLimits/AttributePerEventCountLimit-12 4.249µ ± 1% 4.216µ ± 1% ~ (p=0.066 n=10) SpanLimits/AttributePerLinkCountLimit-12 4.175µ ± 1% 4.226µ ± 0% +1.22% (p=0.037 n=10) SpanSetAttributesOverCapacity-12 1.648µ ± 0% 1.635µ ± 6% ~ (p=0.382 n=10) StartEndSpan/AlwaysSample-12 305.3n ± 1% 298.9n ± 2% -2.10% (p=0.045 n=10) StartEndSpan/NeverSample-12 137.0n ± 0% 132.9n ± 0% -3.03% (p=0.000 n=10) SpanWithAttributes_4/AlwaysSample-12 516.3n ± 1% 507.6n ± 0% -1.68% (p=0.000 n=10) SpanWithAttributes_4/NeverSample-12 228.7n ± 1% 221.8n ± 1% -3.00% (p=0.000 n=10) SpanWithAttributes_8/AlwaysSample-12 706.6n ± 1% 689.0n ± 0% -2.50% (p=0.000 n=10) SpanWithAttributes_8/NeverSample-12 313.0n ± 1% 307.1n ± 0% -1.87% (p=0.000 n=10) SpanWithAttributes_all/AlwaysSample-12 565.0n ± 1% 560.8n ± 0% -0.75% (p=0.002 n=10) SpanWithAttributes_all/NeverSample-12 251.2n ± 1% 247.5n ± 4% -1.45% (p=0.034 n=10) SpanWithAttributes_all_2x/AlwaysSample-12 823.4n ± 1% 812.0n ± 1% -1.39% (p=0.028 n=10) SpanWithAttributes_all_2x/NeverSample-12 368.8n ± 1% 360.6n ± 0% -2.22% (p=0.000 n=10) SpanWithEvents_4/AlwaysSample-12 709.3n ± 0% 699.6n ± 0% -1.37% (p=0.000 n=10) SpanWithEvents_4/NeverSample-12 139.4n ± 0% 137.0n ± 0% -1.72% (p=0.000 n=10) SpanWithEvents_8/AlwaysSample-12 1.091µ ± 1% 1.073µ ± 0% -1.60% (p=0.000 n=10) SpanWithEvents_8/NeverSample-12 142.1n ± 0% 140.1n ± 0% -1.41% (p=0.000 n=10) SpanWithEvents_WithStackTrace/AlwaysSample-12 424.6n ± 0% 417.9n ± 0% -1.57% (p=0.000 n=10) SpanWithEvents_WithStackTrace/NeverSample-12 151.3n ± 0% 148.1n ± 0% -2.15% (p=0.000 n=10) SpanWithEvents_WithTimestamp/AlwaysSample-12 412.6n ± 0% 407.6n ± 0% -1.19% (p=0.000 n=10) SpanWithEvents_WithTimestamp/NeverSample-12 174.5n ± 0% 172.7n ± 0% -1.03% (p=0.000 n=10) TraceIDFromHex-12 57.22n ± 0% 15.88n ± 0% -72.25% (p=0.000 n=10) SpanIDFromHex-12 35.000n ± 0% 8.676n ± 0% -75.21% (p=0.000 n=10) TraceID_DotString-12 42.39n ± 0% 24.22n ± 0% -42.85% (p=0.000 n=10) SpanID_DotString-12 31.41n ± 0% 16.98n ± 0% -45.94% (p=0.000 n=10) SpanProcessorOnEnd/batch:_10,_spans:_10-12 164.0n ± 0% 163.8n ± 0% -0.12% (p=0.021 n=10) SpanProcessorOnEnd/batch:_10,_spans:_100-12 1.640µ ± 0% 1.637µ ± 0% -0.18% (p=0.016 n=10) SpanProcessorOnEnd/batch:_100,_spans:_10-12 164.0n ± 0% 163.7n ± 0% -0.18% (p=0.000 n=10) SpanProcessorOnEnd/batch:_100,_spans:_100-12 1.641µ ± 0% 1.636µ ± 0% -0.30% (p=0.000 n=10) SpanProcessorVerboseLogging-12 6.413µ ± 2% 6.444µ ± 5% ~ (p=0.424 n=10) geomean 204.9n 187.0n -8.69% │ ../private/base.txt │ ../private/new.txt │ │ B/op │ B/op vs base │ Truncate/Unlimited-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/Zero-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/Short-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/ASCII-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/ValidUTF-8-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/InvalidUTF-8-12 16.00 ± 0% 16.00 ± 0% ~ (p=1.000 n=10) ¹ Truncate/MixedUTF-8-12 32.00 ± 0% 32.00 ± 0% ~ (p=1.000 n=10) ¹ RecordingSpanSetAttributes/WithLimit/false-12 6.891Ki ± 0% 6.891Ki ± 0% ~ (p=1.000 n=10) ¹ RecordingSpanSetAttributes/WithLimit/true-12 7.023Ki ± 0% 7.023Ki ± 0% ~ (p=1.000 n=10) ¹ SpanEnd-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ TraceStart/with_a_simple_span-12 528.0 ± 0% 528.0 ± 0% ~ (p=1.000 n=10) ¹ TraceStart/with_several_links-12 704.0 ± 0% 704.0 ± 0% ~ (p=1.000 n=10) ¹ TraceStart/with_attributes-12 784.0 ± 0% 784.0 ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/AttributeValueLengthLimit-12 10.56Ki ± 0% 10.56Ki ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/AttributeCountLimit-12 9.844Ki ± 0% 9.844Ki ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/EventCountLimit-12 9.422Ki ± 0% 9.422Ki ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/LinkCountLimit-12 9.031Ki ± 0% 9.031Ki ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/AttributePerEventCountLimit-12 10.47Ki ± 0% 10.47Ki ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/AttributePerLinkCountLimit-12 10.47Ki ± 0% 10.47Ki ± 0% ~ (p=1.000 n=10) ¹ SpanSetAttributesOverCapacity-12 592.0 ± 0% 592.0 ± 0% ~ (p=1.000 n=10) ¹ StartEndSpan/AlwaysSample-12 528.0 ± 0% 528.0 ± 0% ~ (p=1.000 n=10) ¹ StartEndSpan/NeverSample-12 144.0 ± 0% 144.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_4/AlwaysSample-12 1.016Ki ± 0% 1.016Ki ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_4/NeverSample-12 400.0 ± 0% 400.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_8/AlwaysSample-12 1.516Ki ± 0% 1.516Ki ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_8/NeverSample-12 656.0 ± 0% 656.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_all/AlwaysSample-12 1.141Ki ± 0% 1.141Ki ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_all/NeverSample-12 464.0 ± 0% 464.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_all_2x/AlwaysSample-12 1.891Ki ± 0% 1.891Ki ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_all_2x/NeverSample-12 848.0 ± 0% 848.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_4/AlwaysSample-12 1.016Ki ± 0% 1.016Ki ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_4/NeverSample-12 144.0 ± 0% 144.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_8/AlwaysSample-12 1.641Ki ± 0% 1.641Ki ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_8/NeverSample-12 144.0 ± 0% 144.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_WithStackTrace/AlwaysSample-12 624.0 ± 0% 624.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_WithStackTrace/NeverSample-12 160.0 ± 0% 160.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_WithTimestamp/AlwaysSample-12 648.0 ± 0% 648.0 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_WithTimestamp/NeverSample-12 184.0 ± 0% 184.0 ± 0% ~ (p=1.000 n=10) ¹ TraceIDFromHex-12 16.00 ± 0% 0.00 ± 0% -100.00% (p=0.000 n=10) SpanIDFromHex-12 8.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10) SpanProcessorOnEnd/batch:_10,_spans:_10-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SpanProcessorOnEnd/batch:_10,_spans:_100-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SpanProcessorOnEnd/batch:_100,_spans:_10-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SpanProcessorOnEnd/batch:_100,_spans:_100-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SpanProcessorVerboseLogging-12 9.562Ki ± 0% 9.562Ki ± 0% ~ (p=1.000 n=10) ¹ geomean ² ? ² ³ ¹ all samples are equal ² summaries must be >0 to compute geomean ³ ratios must be >0 to compute geomean │ ../private/base.txt │ ../private/new.txt │ │ allocs/op │ allocs/op vs base │ Truncate/Unlimited-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/Zero-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/Short-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/ASCII-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/ValidUTF-8-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/InvalidUTF-8-12 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ Truncate/MixedUTF-8-12 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ RecordingSpanSetAttributes/WithLimit/false-12 3.000 ± 0% 3.000 ± 0% ~ (p=1.000 n=10) ¹ RecordingSpanSetAttributes/WithLimit/true-12 10.00 ± 0% 10.00 ± 0% ~ (p=1.000 n=10) ¹ SpanEnd-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ TraceStart/with_a_simple_span-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹ TraceStart/with_several_links-12 3.000 ± 0% 3.000 ± 0% ~ (p=1.000 n=10) ¹ TraceStart/with_attributes-12 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/AttributeValueLengthLimit-12 41.00 ± 0% 41.00 ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/AttributeCountLimit-12 38.00 ± 0% 38.00 ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/EventCountLimit-12 35.00 ± 0% 35.00 ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/LinkCountLimit-12 35.00 ± 0% 35.00 ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/AttributePerEventCountLimit-12 38.00 ± 0% 38.00 ± 0% ~ (p=1.000 n=10) ¹ SpanLimits/AttributePerLinkCountLimit-12 38.00 ± 0% 38.00 ± 0% ~ (p=1.000 n=10) ¹ SpanSetAttributesOverCapacity-12 3.000 ± 0% 3.000 ± 0% ~ (p=1.000 n=10) ¹ StartEndSpan/AlwaysSample-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹ StartEndSpan/NeverSample-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_4/AlwaysSample-12 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_4/NeverSample-12 3.000 ± 0% 3.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_8/AlwaysSample-12 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_8/NeverSample-12 3.000 ± 0% 3.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_all/AlwaysSample-12 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_all/NeverSample-12 3.000 ± 0% 3.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_all_2x/AlwaysSample-12 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithAttributes_all_2x/NeverSample-12 3.000 ± 0% 3.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_4/AlwaysSample-12 5.000 ± 0% 5.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_4/NeverSample-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_8/AlwaysSample-12 6.000 ± 0% 6.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_8/NeverSample-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_WithStackTrace/AlwaysSample-12 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_WithStackTrace/NeverSample-12 3.000 ± 0% 3.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_WithTimestamp/AlwaysSample-12 5.000 ± 0% 5.000 ± 0% ~ (p=1.000 n=10) ¹ SpanWithEvents_WithTimestamp/NeverSample-12 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹ TraceIDFromHex-12 1.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10) SpanIDFromHex-12 1.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10) SpanProcessorOnEnd/batch:_10,_spans:_10-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SpanProcessorOnEnd/batch:_10,_spans:_100-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SpanProcessorOnEnd/batch:_100,_spans:_10-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SpanProcessorOnEnd/batch:_100,_spans:_100-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SpanProcessorVerboseLogging-12 36.00 ± 0% 36.00 ± 0% ~ (p=1.000 n=10) ¹ geomean ² ? ² ³ ¹ all samples are equal ² summaries must be >0 to compute geomean ³ ratios must be >0 to compute geomean ``` Issue: #6721
431 lines
11 KiB
Go
431 lines
11 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package trace_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-logr/logr"
|
|
"github.com/go-logr/logr/funcr"
|
|
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/internal/global"
|
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
"go.opentelemetry.io/otel/sdk/trace/tracetest"
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
func benchmarkSpanLimits(b *testing.B, limits sdktrace.SpanLimits) {
|
|
tp := sdktrace.NewTracerProvider(sdktrace.WithSpanLimits(limits))
|
|
tracer := tp.Tracer(b.Name())
|
|
ctx := context.Background()
|
|
|
|
const count = 8
|
|
|
|
attrs := []attribute.KeyValue{
|
|
attribute.Bool("bool", true),
|
|
attribute.BoolSlice("boolSlice", []bool{true, false}),
|
|
attribute.Int("int", 42),
|
|
attribute.IntSlice("intSlice", []int{42, -1}),
|
|
attribute.Int64("int64", 42),
|
|
attribute.Int64Slice("int64Slice", []int64{42, -1}),
|
|
attribute.Float64("float64", 42),
|
|
attribute.Float64Slice("float64Slice", []float64{42, -1}),
|
|
attribute.String("string", "value"),
|
|
attribute.StringSlice("stringSlice", []string{"value", "value-1"}),
|
|
}
|
|
|
|
links := make([]trace.Link, count)
|
|
for i := range links {
|
|
links[i] = trace.Link{
|
|
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: [16]byte{0x01},
|
|
SpanID: [8]byte{0x01},
|
|
}),
|
|
Attributes: attrs,
|
|
}
|
|
}
|
|
|
|
events := make([]struct {
|
|
name string
|
|
attr []attribute.KeyValue
|
|
}, count)
|
|
for i := range events {
|
|
events[i] = struct {
|
|
name string
|
|
attr []attribute.KeyValue
|
|
}{
|
|
name: fmt.Sprintf("event-%d", i),
|
|
attr: attrs,
|
|
}
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := tracer.Start(ctx, "span-name", trace.WithLinks(links...))
|
|
span.SetAttributes(attrs...)
|
|
for _, e := range events {
|
|
span.AddEvent(e.name, trace.WithAttributes(e.attr...))
|
|
}
|
|
span.End()
|
|
}
|
|
}
|
|
|
|
func BenchmarkSpanLimits(b *testing.B) {
|
|
b.Run("AttributeValueLengthLimit", func(b *testing.B) {
|
|
limits := sdktrace.NewSpanLimits()
|
|
limits.AttributeValueLengthLimit = 2
|
|
benchmarkSpanLimits(b, limits)
|
|
})
|
|
|
|
b.Run("AttributeCountLimit", func(b *testing.B) {
|
|
limits := sdktrace.NewSpanLimits()
|
|
limits.AttributeCountLimit = 1
|
|
benchmarkSpanLimits(b, limits)
|
|
})
|
|
|
|
b.Run("EventCountLimit", func(b *testing.B) {
|
|
limits := sdktrace.NewSpanLimits()
|
|
limits.EventCountLimit = 1
|
|
benchmarkSpanLimits(b, limits)
|
|
})
|
|
|
|
b.Run("LinkCountLimit", func(b *testing.B) {
|
|
limits := sdktrace.NewSpanLimits()
|
|
limits.LinkCountLimit = 1
|
|
benchmarkSpanLimits(b, limits)
|
|
})
|
|
|
|
b.Run("AttributePerEventCountLimit", func(b *testing.B) {
|
|
limits := sdktrace.NewSpanLimits()
|
|
limits.AttributePerEventCountLimit = 1
|
|
benchmarkSpanLimits(b, limits)
|
|
})
|
|
|
|
b.Run("AttributePerLinkCountLimit", func(b *testing.B) {
|
|
limits := sdktrace.NewSpanLimits()
|
|
limits.AttributePerLinkCountLimit = 1
|
|
benchmarkSpanLimits(b, limits)
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanSetAttributesOverCapacity(b *testing.B) {
|
|
limits := sdktrace.NewSpanLimits()
|
|
limits.AttributeCountLimit = 1
|
|
tp := sdktrace.NewTracerProvider(sdktrace.WithSpanLimits(limits))
|
|
tracer := tp.Tracer("BenchmarkSpanSetAttributesOverCapacity")
|
|
ctx := context.Background()
|
|
attrs := make([]attribute.KeyValue, 128)
|
|
for i := range attrs {
|
|
key := fmt.Sprintf("key-%d", i)
|
|
attrs[i] = attribute.Bool(key, true)
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := tracer.Start(ctx, "/foo")
|
|
span.SetAttributes(attrs...)
|
|
span.End()
|
|
}
|
|
}
|
|
|
|
func BenchmarkStartEndSpan(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark StartEndSpan", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanWithAttributes_4(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark Start With 4 Attributes", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.SetAttributes(
|
|
attribute.Bool("key1", false),
|
|
attribute.String("key2", "hello"),
|
|
attribute.Int64("key3", 123),
|
|
attribute.Float64("key4", 123.456),
|
|
)
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanWithAttributes_8(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark Start With 8 Attributes", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.SetAttributes(
|
|
attribute.Bool("key1", false),
|
|
attribute.String("key2", "hello"),
|
|
attribute.Int64("key3", 123),
|
|
attribute.Float64("key4", 123.456),
|
|
attribute.Bool("key21", false),
|
|
attribute.String("key22", "hello"),
|
|
attribute.Int64("key23", 123),
|
|
attribute.Float64("key24", 123.456),
|
|
)
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanWithAttributes_all(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark Start With all Attribute types", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.SetAttributes(
|
|
attribute.Bool("key1", false),
|
|
attribute.String("key2", "hello"),
|
|
attribute.Int64("key3", 123),
|
|
attribute.Float64("key7", 123.456),
|
|
attribute.Int("key9", 123),
|
|
)
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanWithAttributes_all_2x(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark Start With all Attributes types twice", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.SetAttributes(
|
|
attribute.Bool("key1", false),
|
|
attribute.String("key2", "hello"),
|
|
attribute.Int64("key3", 123),
|
|
attribute.Float64("key7", 123.456),
|
|
attribute.Int("key10", 123),
|
|
attribute.Bool("key21", false),
|
|
attribute.String("key22", "hello"),
|
|
attribute.Int64("key23", 123),
|
|
attribute.Float64("key27", 123.456),
|
|
attribute.Int("key210", 123),
|
|
)
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanWithEvents_4(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark Start With 4 Events", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.AddEvent("event1")
|
|
span.AddEvent("event2")
|
|
span.AddEvent("event3")
|
|
span.AddEvent("event4")
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanWithEvents_8(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark Start With 4 Events", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.AddEvent("event1")
|
|
span.AddEvent("event2")
|
|
span.AddEvent("event3")
|
|
span.AddEvent("event4")
|
|
span.AddEvent("event5")
|
|
span.AddEvent("event6")
|
|
span.AddEvent("event7")
|
|
span.AddEvent("event8")
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanWithEvents_WithStackTrace(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark Start With 4 Attributes", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.AddEvent("event1", trace.WithStackTrace(true))
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSpanWithEvents_WithTimestamp(b *testing.B) {
|
|
traceBenchmark(b, "Benchmark Start With 4 Attributes", func(b *testing.B, t trace.Tracer) {
|
|
ctx := context.Background()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, span := t.Start(ctx, "/foo")
|
|
span.AddEvent("event1", trace.WithTimestamp(time.Unix(0, 0)))
|
|
span.End()
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkTraceIDFromHex(b *testing.B) {
|
|
want := trace.TraceID{
|
|
0xde,
|
|
0xad,
|
|
0xbe,
|
|
0xef,
|
|
0x01,
|
|
0x23,
|
|
0x45,
|
|
0x67,
|
|
0x89,
|
|
0xab,
|
|
0xcd,
|
|
0xef,
|
|
0x01,
|
|
0x23,
|
|
0x45,
|
|
0x67,
|
|
}
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
got, _ := trace.TraceIDFromHex("deadbeef0123456789abcdef01234567")
|
|
if got != want {
|
|
b.Fatalf("got = %q want = %q", got.String(), want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkSpanIDFromHex(b *testing.B) {
|
|
want := trace.SpanID{0xde, 0xad, 0xbe, 0xef, 0x01, 0x23, 0x45, 0x67}
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
got, _ := trace.SpanIDFromHex("deadbeef01234567")
|
|
if got != want {
|
|
b.Fatalf("got = %q want = %q", got.String(), want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkTraceID_DotString(b *testing.B) {
|
|
t, _ := trace.TraceIDFromHex("0000000000000001000000000000002a")
|
|
sc := trace.NewSpanContext(trace.SpanContextConfig{TraceID: t})
|
|
|
|
want := "0000000000000001000000000000002a"
|
|
for i := 0; i < b.N; i++ {
|
|
if got := sc.TraceID().String(); got != want {
|
|
b.Fatalf("got = %q want = %q", got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkSpanID_DotString(b *testing.B) {
|
|
sc := trace.NewSpanContext(trace.SpanContextConfig{SpanID: trace.SpanID{1}})
|
|
want := "0100000000000000"
|
|
for i := 0; i < b.N; i++ {
|
|
if got := sc.SpanID().String(); got != want {
|
|
b.Fatalf("got = %q want = %q", got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func traceBenchmark(b *testing.B, name string, fn func(*testing.B, trace.Tracer)) {
|
|
b.Run("AlwaysSample", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
fn(b, tracer(b, name, sdktrace.AlwaysSample()))
|
|
})
|
|
b.Run("NeverSample", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
fn(b, tracer(b, name, sdktrace.NeverSample()))
|
|
})
|
|
}
|
|
|
|
func tracer(_ *testing.B, name string, sampler sdktrace.Sampler) trace.Tracer {
|
|
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sampler))
|
|
return tp.Tracer(name)
|
|
}
|
|
|
|
func BenchmarkSpanProcessorOnEnd(b *testing.B) {
|
|
for _, bb := range []struct {
|
|
batchSize int
|
|
spansCount int
|
|
}{
|
|
{batchSize: 10, spansCount: 10},
|
|
{batchSize: 10, spansCount: 100},
|
|
{batchSize: 100, spansCount: 10},
|
|
{batchSize: 100, spansCount: 100},
|
|
} {
|
|
b.Run(fmt.Sprintf("batch: %d, spans: %d", bb.batchSize, bb.spansCount), func(b *testing.B) {
|
|
bsp := sdktrace.NewBatchSpanProcessor(
|
|
tracetest.NewNoopExporter(),
|
|
sdktrace.WithMaxExportBatchSize(bb.batchSize),
|
|
)
|
|
b.Cleanup(func() {
|
|
_ = bsp.Shutdown(context.Background())
|
|
})
|
|
snap := tracetest.SpanStub{}.Snapshot()
|
|
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
// Ensure the export happens for every run
|
|
for j := 0; j < bb.spansCount; j++ {
|
|
bsp.OnEnd(snap)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkSpanProcessorVerboseLogging(b *testing.B) {
|
|
b.Cleanup(func(l logr.Logger) func() {
|
|
return func() { global.SetLogger(l) }
|
|
}(global.GetLogger()))
|
|
global.SetLogger(funcr.New(func(string, string) {}, funcr.Options{Verbosity: 5}))
|
|
tp := sdktrace.NewTracerProvider(
|
|
sdktrace.WithBatcher(
|
|
tracetest.NewNoopExporter(),
|
|
sdktrace.WithMaxExportBatchSize(10),
|
|
))
|
|
b.Cleanup(func() {
|
|
_ = tp.Shutdown(context.Background())
|
|
})
|
|
tracer := tp.Tracer("bench")
|
|
ctx := context.Background()
|
|
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
for range 10 {
|
|
_, span := tracer.Start(ctx, "bench")
|
|
span.End()
|
|
}
|
|
}
|
|
}
|