1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-11-25 22:41:46 +02:00

trace: optimize id parsing and string functions (#6791)

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
This commit is contained in:
Joe Schafer
2025-08-26 05:54:11 -07:00
committed by GitHub
parent 2512a6b087
commit 49be00144e
4 changed files with 168 additions and 48 deletions

View File

@@ -293,6 +293,45 @@ func BenchmarkSpanWithEvents_WithTimestamp(b *testing.B) {
})
}
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})