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]) } diff --git a/v3/internal/trace_id_generator_test.go b/v3/internal/trace_id_generator_test.go index 570380259..aa786779d 100644 --- a/v3/internal/trace_id_generator_test.go +++ b/v3/internal/trace_id_generator_test.go @@ -32,3 +32,18 @@ func BenchmarkTraceIDGenerator(b *testing.B) { } } } + +func BenchmarkTraceIDGeneratorParallel(b *testing.B) { + tg := NewTraceIDGenerator(12345) + + b.ResetTimer() + b.ReportAllocs() + + b.RunParallel(func(p *testing.PB) { + for p.Next() { + if id := tg.GenerateSpanID(); id == "" { + b.Fatal(id) + } + } + }) +}