Source file
src/log/slog/value_access_benchmark_test.go
1
2
3
4
5
6
7 package slog
8
9 import (
10 "testing"
11 "time"
12 )
13
14
15
16
17
18
19 func BenchmarkDispatch(b *testing.B) {
20 vs := []Value{
21 Int64Value(32768),
22 Uint64Value(0xfacecafe),
23 StringValue("anything"),
24 BoolValue(true),
25 Float64Value(1.2345),
26 DurationValue(time.Second),
27 AnyValue(b),
28 }
29 var (
30 ii int64
31 s string
32 bb bool
33 u uint64
34 d time.Duration
35 f float64
36 a any
37 )
38 b.Run("switch-checked", func(b *testing.B) {
39 for i := 0; i < b.N; i++ {
40 for _, v := range vs {
41 switch v.Kind() {
42 case KindString:
43 s = v.String()
44 case KindInt64:
45 ii = v.Int64()
46 case KindUint64:
47 u = v.Uint64()
48 case KindFloat64:
49 f = v.Float64()
50 case KindBool:
51 bb = v.Bool()
52 case KindDuration:
53 d = v.Duration()
54 case KindAny:
55 a = v.Any()
56 default:
57 panic("bad kind")
58 }
59 }
60 }
61 _ = ii
62 _ = s
63 _ = bb
64 _ = u
65 _ = d
66 _ = f
67 _ = a
68
69 })
70 b.Run("As", func(b *testing.B) {
71 for i := 0; i < b.N; i++ {
72 for _, kv := range vs {
73 if v, ok := kv.AsString(); ok {
74 s = v
75 } else if v, ok := kv.AsInt64(); ok {
76 ii = v
77 } else if v, ok := kv.AsUint64(); ok {
78 u = v
79 } else if v, ok := kv.AsFloat64(); ok {
80 f = v
81 } else if v, ok := kv.AsBool(); ok {
82 bb = v
83 } else if v, ok := kv.AsDuration(); ok {
84 d = v
85 } else if v, ok := kv.AsAny(); ok {
86 a = v
87 } else {
88 panic("bad kind")
89 }
90 }
91 }
92 _ = ii
93 _ = s
94 _ = bb
95 _ = u
96 _ = d
97 _ = f
98 _ = a
99 })
100
101 b.Run("Visit", func(b *testing.B) {
102 v := &setVisitor{}
103 b.ResetTimer()
104 for i := 0; i < b.N; i++ {
105 for _, kv := range vs {
106 kv.Visit(v)
107 }
108 }
109 })
110 }
111
112 type setVisitor struct {
113 i int64
114 s string
115 b bool
116 u uint64
117 d time.Duration
118 f float64
119 a any
120 }
121
122 func (v *setVisitor) String(s string) { v.s = s }
123 func (v *setVisitor) Int64(i int64) { v.i = i }
124 func (v *setVisitor) Uint64(x uint64) { v.u = x }
125 func (v *setVisitor) Float64(x float64) { v.f = x }
126 func (v *setVisitor) Bool(x bool) { v.b = x }
127 func (v *setVisitor) Duration(x time.Duration) { v.d = x }
128 func (v *setVisitor) Any(x any) { v.a = x }
129
130
131
132
133
134 func (a Value) AsString() (string, bool) {
135 if a.Kind() == KindString {
136 return a.str(), true
137 }
138 return "", false
139 }
140
141 func (a Value) AsInt64() (int64, bool) {
142 if a.Kind() == KindInt64 {
143 return int64(a.num), true
144 }
145 return 0, false
146 }
147
148 func (a Value) AsUint64() (uint64, bool) {
149 if a.Kind() == KindUint64 {
150 return a.num, true
151 }
152 return 0, false
153 }
154
155 func (a Value) AsFloat64() (float64, bool) {
156 if a.Kind() == KindFloat64 {
157 return a.float(), true
158 }
159 return 0, false
160 }
161
162 func (a Value) AsBool() (bool, bool) {
163 if a.Kind() == KindBool {
164 return a.bool(), true
165 }
166 return false, false
167 }
168
169 func (a Value) AsDuration() (time.Duration, bool) {
170 if a.Kind() == KindDuration {
171 return a.duration(), true
172 }
173 return 0, false
174 }
175
176 func (a Value) AsAny() (any, bool) {
177 if a.Kind() == KindAny {
178 return a.any, true
179 }
180 return nil, false
181 }
182
183
184
185
186 type Visitor interface {
187 String(string)
188 Int64(int64)
189 Uint64(uint64)
190 Float64(float64)
191 Bool(bool)
192 Duration(time.Duration)
193 Any(any)
194 }
195
196 func (a Value) Visit(v Visitor) {
197 switch a.Kind() {
198 case KindString:
199 v.String(a.str())
200 case KindInt64:
201 v.Int64(int64(a.num))
202 case KindUint64:
203 v.Uint64(a.num)
204 case KindBool:
205 v.Bool(a.bool())
206 case KindFloat64:
207 v.Float64(a.float())
208 case KindDuration:
209 v.Duration(a.duration())
210 case KindAny:
211 v.Any(a.any)
212 default:
213 panic("bad kind")
214 }
215 }
216
View as plain text