perf(trace): avoid to allocate option struct in span tracking

from:
Benchmark_Span_TrackLog
Benchmark_Span_TrackLog/duration-any
Benchmark_Span_TrackLog/duration-any-4      7892170  457.1 ns/op  40 B/op  3 allocs/op
Benchmark_Span_TrackLog/duration-second
Benchmark_Span_TrackLog/duration-second-4  10384854  113.5 ns/op  28 B/op  3 allocs/op
Benchmark_Span_TrackLog/duration-error
Benchmark_Span_TrackLog/duration-error-4    5301676  500.1 ns/op  80 B/op  6 allocs/op

to:
Benchmark_Span_TrackLog
Benchmark_Span_TrackLog/duration-any
Benchmark_Span_TrackLog/duration-any-4     11378097  97.32 ns/op  16 B/op  1 allocs/op
Benchmark_Span_TrackLog/duration-second
Benchmark_Span_TrackLog/duration-second-4  17787051  211.9 ns/op  24 B/op  3 allocs/op
Benchmark_Span_TrackLog/duration-error
Benchmark_Span_TrackLog/duration-error-4    9427880  189.0 ns/op  40 B/op  3 allocs/op

. #23135507

Signed-off-by: slasher <shenjie1@oppo.com>
This commit is contained in:
slasher 2025-03-03 15:21:17 +08:00
parent ad4e8b0f9f
commit ac1e84bf0b
3 changed files with 73 additions and 22 deletions

View File

@ -266,9 +266,9 @@ func (s *spanImpl) AppendTrackLog(module string, startTime time.Time, err error,
// AppendTrackLogWithDuration records cost time with duration for a calling to a module and
// appends to baggage with default key fieldTrackLogKey.
func (s *spanImpl) AppendTrackLogWithDuration(module string, duration time.Duration, err error, opts ...SpanOption) {
spanOpt := &spanOptions{duration: durationMs, errorLength: maxErrorLen} // compatibility
spanOpt := spanOptions{duration: durationMs, errorLength: maxErrorLen} // compatibility
for _, opt := range opts {
opt(spanOpt)
spanOpt = opt(spanOpt)
}
if spanOpt.duration == durationAny {
@ -283,10 +283,12 @@ func (s *spanImpl) AppendTrackLogWithDuration(module string, duration time.Durat
if err != nil {
msg := err.Error()
errLen := spanOpt.errorLength
if len(msg) > errLen {
if len(msg) > int(errLen) {
msg = msg[:errLen]
}
module += "/" + msg
if len(msg) > 0 {
module += "/" + msg
}
}
s.track(module)
}

View File

@ -19,7 +19,7 @@ import (
)
// TracerOption is a function that sets some option on the tracer
type SpanOption func(*spanOptions)
type SpanOption func(spanOptions) spanOptions
type spanOptionDuration uint8
@ -78,23 +78,59 @@ func (d spanOptionDuration) Unit(duration time.Duration) string {
type spanOptions struct {
duration spanOptionDuration
durationUnit bool
errorLength int
errorLength uint16
}
func OptSpanDurationAny() SpanOption { return func(o *spanOptions) { o.duration = durationAny } }
func OptSpanDurationNone() SpanOption { return func(o *spanOptions) { o.duration = durationNone } }
func OptSpanDurationNs() SpanOption { return func(o *spanOptions) { o.duration = durationNs } }
func OptSpanDurationUs() SpanOption { return func(o *spanOptions) { o.duration = durationUs } }
func OptSpanDurationMs() SpanOption { return func(o *spanOptions) { o.duration = durationMs } }
func OptSpanDurationSecond() SpanOption { return func(o *spanOptions) { o.duration = durationSecond } }
func OptSpanDurationMinute() SpanOption { return func(o *spanOptions) { o.duration = durationMinute } }
func OptSpanDurationHour() SpanOption { return func(o *spanOptions) { o.duration = durationHour } }
func OptSpanDurationUnit() SpanOption { return func(o *spanOptions) { o.durationUnit = true } }
var (
_durationAny = durTemplate(durationAny)
_durationNone = durTemplate(durationNone)
_durationNs = durTemplate(durationNs)
_durationUs = durTemplate(durationUs)
_durationMs = durTemplate(durationMs)
_durationSecond = durTemplate(durationSecond)
_durationMinute = durTemplate(durationMinute)
_durationHour = durTemplate(durationHour)
_durationUnit = func(o spanOptions) spanOptions { o.durationUnit = true; return o }
func OptSpanErrorLength(l int) SpanOption {
return func(o *spanOptions) {
if l >= 0 {
o.errorLength = l
_mapErrorLength = func() map[int]SpanOption { // pre-allocation
m := make(map[int]SpanOption, maxErrorLen+2)
for ii := 0; ii <= maxErrorLen; ii++ {
length := ii
m[ii] = func(o spanOptions) spanOptions { o.errorLength = uint16(length); return o }
}
m[-1] = func(o spanOptions) spanOptions { o.errorLength = maxErrorLen; return o }
return m
}()
)
func durTemplate(od spanOptionDuration) SpanOption {
return func(o spanOptions) spanOptions { o.duration = od; return o }
}
func OptSpanDurationAny() SpanOption { return _durationAny }
func OptSpanDurationNone() SpanOption { return _durationNone }
func OptSpanDurationNs() SpanOption { return _durationNs }
func OptSpanDurationUs() SpanOption { return _durationUs }
func OptSpanDurationMs() SpanOption { return _durationMs }
func OptSpanDurationSecond() SpanOption { return _durationSecond }
func OptSpanDurationMinute() SpanOption { return _durationMinute }
func OptSpanDurationHour() SpanOption { return _durationHour }
func OptSpanDurationUnit() SpanOption { return _durationUnit }
func OptSpanErrorLength(l int) SpanOption {
if l < 0 {
return _mapErrorLength[-1]
}
if l <= maxErrorLen {
return _mapErrorLength[l]
}
heapl := l
return func(o spanOptions) spanOptions {
o.errorLength = uint16(heapl)
return o
}
}
var (
ConstOptSpanAny = []SpanOption{OptSpanDurationAny()}
ConstOptSpanUs = []SpanOption{OptSpanDurationUs(), OptSpanDurationUnit()}
ConstOptSpanMs = []SpanOption{OptSpanDurationMs(), OptSpanDurationUnit()}
)

View File

@ -268,6 +268,18 @@ func TestSpan_TrackLogWithOption(t *testing.T) {
t.Log(span.TrackLog())
span.AppendTrackLogWithDuration("em", duration, err, OptSpanDurationAny(), OptSpanErrorLength(3))
t.Log(span.TrackLog())
longstring := "long error"
for range [8]struct{}{} {
longstring += " long error"
}
errLong := errors.New(longstring)
for idx := range [maxErrorLen + 6]struct{}{} {
spanError, _ := StartSpanFromContext(context.Background(), "test trackLog error length")
spanError.AppendTrackLogWithDuration("err", duration, errLong, OptSpanErrorLength(idx-2))
t.Log(spanError.TrackLog())
spanError.Finish()
}
}
func TestSpan_BaseLogger(t *testing.T) {
@ -382,17 +394,18 @@ func Benchmark_Span_TrackLog(b *testing.B) {
b.ResetTimer()
b.Run("duration-any", func(b *testing.B) {
for ii := 0; ii < b.N; ii++ {
span.AppendTrackLogWithDuration(module, duration, nil, OptSpanDurationAny())
span.AppendTrackLogWithDuration(module, duration, nil, ConstOptSpanAny...)
}
})
b.Run("duration-second", func(b *testing.B) {
for ii := 0; ii < b.N; ii++ {
span.AppendTrackLogWithDuration(module, duration, nil, OptSpanDurationSecond())
span.AppendTrackLogWithDuration(module, duration, nil, ConstOptSpanMs...)
}
})
b.Run("duration-error", func(b *testing.B) {
opts := []SpanOption{OptSpanErrorLength(13)}
for ii := 0; ii < b.N; ii++ {
span.AppendTrackLogWithDuration(module, duration, err, OptSpanErrorLength(13))
span.AppendTrackLogWithDuration(module, duration, err, opts...)
}
})
}