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 for b.Loop() {
104 for _, kv := range vs {
105 kv.Visit(v)
106 }
107 }
108 })
109 }
110
111 type setVisitor struct {
112 i int64
113 s string
114 b bool
115 u uint64
116 d time.Duration
117 f float64
118 a any
119 }
120
121 func (v *setVisitor) String(s string) { v.s = s }
122 func (v *setVisitor) Int64(i int64) { v.i = i }
123 func (v *setVisitor) Uint64(x uint64) { v.u = x }
124 func (v *setVisitor) Float64(x float64) { v.f = x }
125 func (v *setVisitor) Bool(x bool) { v.b = x }
126 func (v *setVisitor) Duration(x time.Duration) { v.d = x }
127 func (v *setVisitor) Any(x any) { v.a = x }
128
129
130
131
132
133 func (a Value) AsString() (string, bool) {
134 if a.Kind() == KindString {
135 return a.str(), true
136 }
137 return "", false
138 }
139
140 func (a Value) AsInt64() (int64, bool) {
141 if a.Kind() == KindInt64 {
142 return int64(a.num), true
143 }
144 return 0, false
145 }
146
147 func (a Value) AsUint64() (uint64, bool) {
148 if a.Kind() == KindUint64 {
149 return a.num, true
150 }
151 return 0, false
152 }
153
154 func (a Value) AsFloat64() (float64, bool) {
155 if a.Kind() == KindFloat64 {
156 return a.float(), true
157 }
158 return 0, false
159 }
160
161 func (a Value) AsBool() (bool, bool) {
162 if a.Kind() == KindBool {
163 return a.bool(), true
164 }
165 return false, false
166 }
167
168 func (a Value) AsDuration() (time.Duration, bool) {
169 if a.Kind() == KindDuration {
170 return a.duration(), true
171 }
172 return 0, false
173 }
174
175 func (a Value) AsAny() (any, bool) {
176 if a.Kind() == KindAny {
177 return a.any, true
178 }
179 return nil, false
180 }
181
182
183
184
185 type Visitor interface {
186 String(string)
187 Int64(int64)
188 Uint64(uint64)
189 Float64(float64)
190 Bool(bool)
191 Duration(time.Duration)
192 Any(any)
193 }
194
195 func (a Value) Visit(v Visitor) {
196 switch a.Kind() {
197 case KindString:
198 v.String(a.str())
199 case KindInt64:
200 v.Int64(int64(a.num))
201 case KindUint64:
202 v.Uint64(a.num)
203 case KindBool:
204 v.Bool(a.bool())
205 case KindFloat64:
206 v.Float64(a.float())
207 case KindDuration:
208 v.Duration(a.duration())
209 case KindAny:
210 v.Any(a.any)
211 default:
212 panic("bad kind")
213 }
214 }
215
View as plain text