From ce4def835c933a45f9bd4dfcb728b07b30b52c22 Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 21 Oct 2024 20:23:57 +0200 Subject: [PATCH] Avoid an additional allocation for the encoding We can pre-allocate a large-enough buffer, and then in-place encode the bits to avoid the allocation done by hex.EncodeToString(). Effectively this shaves a couple of ns off the generation: --- v3/internal/trace_id_generator.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/v3/internal/trace_id_generator.go b/v3/internal/trace_id_generator.go index 4a1f5ba9d..9892d0e4d 100644 --- a/v3/internal/trace_id_generator.go +++ b/v3/internal/trace_id_generator.go @@ -4,7 +4,6 @@ package internal import ( - "encoding/hex" "math/rand" "sync" ) @@ -39,6 +38,10 @@ const ( maxIDByteLen = 16 ) +const ( + hextable = "0123456789abcdef" +) + // GenerateTraceID creates a new trace identifier, which is a 32 character hex string. func (tg *TraceIDGenerator) GenerateTraceID() string { return tg.generateID(traceIDByteLen) @@ -50,9 +53,15 @@ func (tg *TraceIDGenerator) GenerateSpanID() string { } func (tg *TraceIDGenerator) generateID(len int) string { - var bits [maxIDByteLen]byte + var bits [maxIDByteLen * 2]byte tg.Lock() defer tg.Unlock() tg.rnd.Read(bits[:len]) - return hex.EncodeToString(bits[:len]) + + // In-place encode + for i := len - 1; i >= 0; i-- { + bits[i*2+1] = hextable[bits[i]&0x0f] + bits[i*2] = hextable[bits[i]>>4] + } + return string(bits[:len*2]) }