golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/slog/benchmarks/benchmarks_test.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package benchmarks 6 7 import ( 8 "context" 9 "flag" 10 "io" 11 "testing" 12 13 "golang.org/x/exp/slog" 14 "golang.org/x/exp/slog/internal" 15 ) 16 17 func init() { 18 flag.BoolVar(&internal.IgnorePC, "nopc", false, "do not invoke runtime.Callers") 19 } 20 21 // We pass Attrs (or zap.Fields) inline because it affects allocations: building 22 // up a list outside of the benchmarked code and passing it in with "..." 23 // reduces measured allocations. 24 25 func BenchmarkAttrs(b *testing.B) { 26 ctx := context.Background() 27 for _, handler := range []struct { 28 name string 29 h slog.Handler 30 }{ 31 {"disabled", disabledHandler{}}, 32 {"async discard", newAsyncHandler()}, 33 {"fastText discard", newFastTextHandler(io.Discard)}, 34 {"Text discard", slog.NewTextHandler(io.Discard, nil)}, 35 {"JSON discard", slog.NewJSONHandler(io.Discard, nil)}, 36 } { 37 logger := slog.New(handler.h) 38 b.Run(handler.name, func(b *testing.B) { 39 for _, call := range []struct { 40 name string 41 f func() 42 }{ 43 { 44 // The number should match nAttrsInline in slog/record.go. 45 // This should exercise the code path where no allocations 46 // happen in Record or Attr. If there are allocations, they 47 // should only be from Duration.String and Time.String. 48 "5 args", 49 func() { 50 logger.LogAttrs(nil, slog.LevelInfo, TestMessage, 51 slog.String("string", TestString), 52 slog.Int("status", TestInt), 53 slog.Duration("duration", TestDuration), 54 slog.Time("time", TestTime), 55 slog.Any("error", TestError), 56 ) 57 }, 58 }, 59 { 60 "5 args ctx", 61 func() { 62 logger.LogAttrs(ctx, slog.LevelInfo, TestMessage, 63 slog.String("string", TestString), 64 slog.Int("status", TestInt), 65 slog.Duration("duration", TestDuration), 66 slog.Time("time", TestTime), 67 slog.Any("error", TestError), 68 ) 69 }, 70 }, 71 { 72 "10 args", 73 func() { 74 logger.LogAttrs(nil, slog.LevelInfo, TestMessage, 75 slog.String("string", TestString), 76 slog.Int("status", TestInt), 77 slog.Duration("duration", TestDuration), 78 slog.Time("time", TestTime), 79 slog.Any("error", TestError), 80 slog.String("string", TestString), 81 slog.Int("status", TestInt), 82 slog.Duration("duration", TestDuration), 83 slog.Time("time", TestTime), 84 slog.Any("error", TestError), 85 ) 86 }, 87 }, 88 { 89 "40 args", 90 func() { 91 logger.LogAttrs(nil, slog.LevelInfo, TestMessage, 92 slog.String("string", TestString), 93 slog.Int("status", TestInt), 94 slog.Duration("duration", TestDuration), 95 slog.Time("time", TestTime), 96 slog.Any("error", TestError), 97 slog.String("string", TestString), 98 slog.Int("status", TestInt), 99 slog.Duration("duration", TestDuration), 100 slog.Time("time", TestTime), 101 slog.Any("error", TestError), 102 slog.String("string", TestString), 103 slog.Int("status", TestInt), 104 slog.Duration("duration", TestDuration), 105 slog.Time("time", TestTime), 106 slog.Any("error", TestError), 107 slog.String("string", TestString), 108 slog.Int("status", TestInt), 109 slog.Duration("duration", TestDuration), 110 slog.Time("time", TestTime), 111 slog.Any("error", TestError), 112 slog.String("string", TestString), 113 slog.Int("status", TestInt), 114 slog.Duration("duration", TestDuration), 115 slog.Time("time", TestTime), 116 slog.Any("error", TestError), 117 slog.String("string", TestString), 118 slog.Int("status", TestInt), 119 slog.Duration("duration", TestDuration), 120 slog.Time("time", TestTime), 121 slog.Any("error", TestError), 122 slog.String("string", TestString), 123 slog.Int("status", TestInt), 124 slog.Duration("duration", TestDuration), 125 slog.Time("time", TestTime), 126 slog.Any("error", TestError), 127 slog.String("string", TestString), 128 slog.Int("status", TestInt), 129 slog.Duration("duration", TestDuration), 130 slog.Time("time", TestTime), 131 slog.Any("error", TestError), 132 ) 133 }, 134 }, 135 } { 136 b.Run(call.name, func(b *testing.B) { 137 b.ReportAllocs() 138 b.RunParallel(func(pb *testing.PB) { 139 for pb.Next() { 140 call.f() 141 } 142 }) 143 }) 144 } 145 }) 146 } 147 }