1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-09-16 09:26:25 +02:00
Files
opentelemetry-go/trace/hex.go
Joe Schafer 49be00144e 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
2025-08-26 14:54:11 +02:00

39 lines
2.0 KiB
Go

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package trace // import "go.opentelemetry.io/otel/trace"
const (
// hexLU is a hex lookup table of the 16 lowercase hex digits.
// The character values of the string are indexed at the equivalent
// hexadecimal value they represent. This table efficiently encodes byte data
// into a string representation of hexadecimal.
hexLU = "0123456789abcdef"
// hexRev is a reverse hex lookup table for lowercase hex digits.
// The table is efficiently decodes a hexadecimal string into bytes.
// Valid hexadecimal characters are indexed at their respective values. All
// other invalid ASCII characters are represented with '\xff'.
//
// The '\xff' character is used as invalid because no valid character has
// the upper 4 bits set. Meaning, an efficient validation can be performed
// over multiple character parsing by checking these bits remain zero.
hexRev = "" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
)