github.com/uber-go/tally/v4@v4.1.17/scope_benchmark_test.go (about) 1 // Copyright (c) 2021 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package tally 22 23 import ( 24 "fmt" 25 "strconv" 26 "sync/atomic" 27 "testing" 28 "time" 29 ) 30 31 func BenchmarkNameGeneration(b *testing.B) { 32 root, _ := NewRootScope(ScopeOptions{ 33 Prefix: "funkytown", 34 Reporter: NullStatsReporter, 35 }, 0) 36 s := root.(*scope) 37 for n := 0; n < b.N; n++ { 38 s.fullyQualifiedName("take.me.to") 39 } 40 } 41 42 func BenchmarkCounterAllocation(b *testing.B) { 43 root, _ := NewRootScope(ScopeOptions{ 44 Prefix: "funkytown", 45 Reporter: NullStatsReporter, 46 }, 0) 47 s := root.(*scope) 48 49 ids := make([]string, 0, b.N) 50 for i := 0; i < b.N; i++ { 51 ids = append(ids, fmt.Sprintf("take.me.to.%d", i)) 52 } 53 b.ResetTimer() 54 55 for n := 0; n < b.N; n++ { 56 s.Counter(ids[n]) 57 } 58 } 59 60 func BenchmarkSanitizedCounterAllocation(b *testing.B) { 61 root, _ := NewRootScope(ScopeOptions{ 62 Prefix: "funkytown", 63 Reporter: NullStatsReporter, 64 SanitizeOptions: &alphanumericSanitizerOpts, 65 }, 0) 66 s := root.(*scope) 67 68 ids := make([]string, 0, b.N) 69 for i := 0; i < b.N; i++ { 70 ids = append(ids, fmt.Sprintf("take.me.to.%d", i)) 71 } 72 b.ResetTimer() 73 74 for n := 0; n < b.N; n++ { 75 s.Counter(ids[n]) 76 } 77 } 78 79 func BenchmarkNameGenerationTagged(b *testing.B) { 80 root, _ := NewRootScope(ScopeOptions{ 81 Prefix: "funkytown", 82 Tags: map[string]string{ 83 "style": "funky", 84 "hair": "wavy", 85 "jefferson": "starship", 86 }, 87 Reporter: NullStatsReporter, 88 }, 0) 89 s := root.(*scope) 90 for n := 0; n < b.N; n++ { 91 s.fullyQualifiedName("take.me.to") 92 } 93 } 94 95 func BenchmarkScopeTaggedCachedSubscopes(b *testing.B) { 96 root, _ := NewRootScope(ScopeOptions{ 97 Prefix: "funkytown", 98 Reporter: NullStatsReporter, 99 Tags: map[string]string{ 100 "style": "funky", 101 "hair": "wavy", 102 "jefferson": "starship", 103 }, 104 }, 0) 105 b.ResetTimer() 106 107 for n := 0; n < b.N; n++ { 108 root.Tagged(map[string]string{ 109 "foo": "bar", 110 "baz": "qux", 111 "qux": "quux", 112 }) 113 } 114 } 115 116 func BenchmarkScopeTaggedNoCachedSubscopes(b *testing.B) { 117 root, _ := NewRootScope(ScopeOptions{ 118 Prefix: "funkytown", 119 Reporter: NullStatsReporter, 120 Tags: map[string]string{ 121 "style": "funky", 122 "hair": "wavy", 123 "jefferson": "starship", 124 }, 125 }, 0) 126 127 values := make([]string, b.N) 128 for i := 0; i < b.N; i++ { 129 values[i] = strconv.Itoa(i) 130 } 131 132 b.ResetTimer() 133 134 for n := 0; n < b.N; n++ { 135 root.Tagged(map[string]string{ 136 "foo": values[n], 137 "baz": values[n], 138 "qux": values[n], 139 }) 140 } 141 } 142 143 func BenchmarkScopeTaggedNoCachedSubscopesParallel(b *testing.B) { 144 root, _ := NewRootScope(ScopeOptions{ 145 Prefix: "funkytown", 146 Reporter: NullStatsReporter, 147 Tags: map[string]string{ 148 "style": "funky", 149 "hair": "wavy", 150 "jefferson": "starship", 151 }, 152 }, 0) 153 154 b.ResetTimer() 155 156 index := int64(0) 157 b.RunParallel(func(pb *testing.PB) { 158 for pb.Next() { 159 n := atomic.AddInt64(&index, 1) 160 value := strconv.Itoa(int(n)) 161 162 // Validated that the compiler is not optimizing this with a cpu profiler. 163 // Check https://github.com/uber-go/tally/pull/184 for more details 164 root.Tagged(map[string]string{ 165 "foo": value, 166 "baz": value, 167 "qux": value, 168 }) 169 } 170 }) 171 } 172 173 func BenchmarkScopeTaggedNoCachedSubscopesParallelPercentageCached(b *testing.B) { 174 percentageCached := int64(5) 175 root, _ := NewRootScope(ScopeOptions{ 176 Prefix: "funkytown", 177 Reporter: NullStatsReporter, 178 Tags: map[string]string{ 179 "style": "funky", 180 "hair": "wavy", 181 "jefferson": "starship", 182 }, 183 }, 0) 184 185 cachedMap := map[string]string{ 186 "foo": "any", 187 "baz": "any", 188 "qux": "any", 189 } 190 root.Tagged(cachedMap) 191 192 b.ResetTimer() 193 194 index := int64(-1) 195 b.RunParallel(func(pb *testing.PB) { 196 for pb.Next() { 197 n := atomic.AddInt64(&index, 1) 198 199 if (n % 100) < percentageCached { 200 root.Tagged(cachedMap) 201 continue 202 } 203 204 value := strconv.Itoa(int(n)) 205 206 // Validated that the compiler is not optimizing this with a cpu profiler. 207 // Check https://github.com/uber-go/tally/pull/184 for more details 208 root.Tagged(map[string]string{ 209 "foo": value, 210 "baz": value, 211 "qux": value, 212 }) 213 } 214 }) 215 } 216 217 func BenchmarkNameGenerationNoPrefix(b *testing.B) { 218 root, _ := NewRootScope(ScopeOptions{ 219 Reporter: NullStatsReporter, 220 }, 0) 221 s := root.(*scope) 222 for n := 0; n < b.N; n++ { 223 s.fullyQualifiedName("im.all.alone") 224 } 225 } 226 227 func BenchmarkHistogramAllocation(b *testing.B) { 228 root, _ := NewRootScope(ScopeOptions{ 229 Reporter: NullStatsReporter, 230 }, 0) 231 b.ReportAllocs() 232 b.ResetTimer() 233 for i := 0; i < b.N; i++ { 234 root.Histogram("foo"+strconv.Itoa(i), DefaultBuckets) 235 } 236 } 237 238 func BenchmarkHistogramExisting(b *testing.B) { 239 root, _ := NewRootScope(ScopeOptions{ 240 Reporter: NullStatsReporter, 241 }, 0) 242 b.ReportAllocs() 243 b.ResetTimer() 244 for i := 0; i < b.N; i++ { 245 root.Histogram("foo", DefaultBuckets) 246 } 247 } 248 249 func benchmarkScopeReportingN(b *testing.B, numElems int) { 250 root, _ := NewRootScope(ScopeOptions{ 251 Prefix: "funkytown", 252 CachedReporter: noopCachedReporter{}, 253 SanitizeOptions: &alphanumericSanitizerOpts, 254 }, 0) 255 s := root.(*scope) 256 257 ids := make([]string, 0, numElems) 258 for i := 0; i < numElems; i++ { 259 id := fmt.Sprintf("take.me.to.%d", i) 260 ids = append(ids, id) 261 s.Counter(id) 262 } 263 _ = ids 264 b.ResetTimer() 265 266 for n := 0; n < b.N; n++ { 267 s.cachedReport() 268 } 269 } 270 271 func BenchmarkScopeReporting(b *testing.B) { 272 for i := 1; i <= 1000000; i *= 10 { 273 size := fmt.Sprintf("size%d", i) 274 b.Run(size, func(b *testing.B) { 275 benchmarkScopeReportingN(b, i) 276 }) 277 } 278 } 279 280 type noopStat struct{} 281 282 func (s noopStat) ReportCount(value int64) {} 283 func (s noopStat) ReportGauge(value float64) {} 284 func (s noopStat) ReportTimer(interval time.Duration) {} 285 func (s noopStat) ValueBucket(bucketLowerBound, bucketUpperBound float64) CachedHistogramBucket { 286 return s 287 } 288 func (s noopStat) DurationBucket(bucketLowerBound, bucketUpperBound time.Duration) CachedHistogramBucket { 289 return s 290 } 291 func (s noopStat) ReportSamples(value int64) {} 292 293 type noopCachedReporter struct{} 294 295 func (n noopCachedReporter) Capabilities() Capabilities { 296 return n 297 } 298 299 func (n noopCachedReporter) Reporting() bool { return true } 300 func (n noopCachedReporter) Tagging() bool { return true } 301 func (n noopCachedReporter) Flush() {} 302 303 func (n noopCachedReporter) ReportCounter(name string, tags map[string]string, value int64) {} 304 func (n noopCachedReporter) ReportGauge(name string, tags map[string]string, value float64) {} 305 306 func (n noopCachedReporter) ReportTimer(name string, tags map[string]string, interval time.Duration) { 307 } 308 309 func (n noopCachedReporter) ReportHistogramValueSamples(name string, tags map[string]string, buckets Buckets, bucketLowerBound float64, bucketUpperBound float64, samples int64) { 310 } 311 func (n noopCachedReporter) ReportHistogramDurationSamples(name string, tags map[string]string, buckets Buckets, bucketLowerBound time.Duration, bucketUpperBound time.Duration, samples int64) { 312 } 313 314 func (n noopCachedReporter) AllocateCounter(name string, tags map[string]string) CachedCount { 315 return noopStat{} 316 } 317 318 func (n noopCachedReporter) AllocateGauge(name string, tags map[string]string) CachedGauge { 319 return noopStat{} 320 } 321 322 func (n noopCachedReporter) AllocateTimer(name string, tags map[string]string) CachedTimer { 323 return noopStat{} 324 } 325 func (n noopCachedReporter) AllocateHistogram(name string, tags map[string]string, buckets Buckets) CachedHistogram { 326 return noopStat{} 327 }