github.com/calmw/ethereum@v0.1.1/metrics/sample_test.go (about) 1 package metrics 2 3 import ( 4 "math" 5 "math/rand" 6 "runtime" 7 "testing" 8 "time" 9 ) 10 11 // Benchmark{Compute,Copy}{1000,1000000} demonstrate that, even for relatively 12 // expensive computations like Variance, the cost of copying the Sample, as 13 // approximated by a make and copy, is much greater than the cost of the 14 // computation for small samples and only slightly less for large samples. 15 func BenchmarkCompute1000(b *testing.B) { 16 s := make([]int64, 1000) 17 for i := 0; i < len(s); i++ { 18 s[i] = int64(i) 19 } 20 b.ResetTimer() 21 for i := 0; i < b.N; i++ { 22 SampleVariance(s) 23 } 24 } 25 func BenchmarkCompute1000000(b *testing.B) { 26 s := make([]int64, 1000000) 27 for i := 0; i < len(s); i++ { 28 s[i] = int64(i) 29 } 30 b.ResetTimer() 31 for i := 0; i < b.N; i++ { 32 SampleVariance(s) 33 } 34 } 35 func BenchmarkCopy1000(b *testing.B) { 36 s := make([]int64, 1000) 37 for i := 0; i < len(s); i++ { 38 s[i] = int64(i) 39 } 40 b.ResetTimer() 41 for i := 0; i < b.N; i++ { 42 sCopy := make([]int64, len(s)) 43 copy(sCopy, s) 44 } 45 } 46 func BenchmarkCopy1000000(b *testing.B) { 47 s := make([]int64, 1000000) 48 for i := 0; i < len(s); i++ { 49 s[i] = int64(i) 50 } 51 b.ResetTimer() 52 for i := 0; i < b.N; i++ { 53 sCopy := make([]int64, len(s)) 54 copy(sCopy, s) 55 } 56 } 57 58 func BenchmarkExpDecaySample257(b *testing.B) { 59 benchmarkSample(b, NewExpDecaySample(257, 0.015)) 60 } 61 62 func BenchmarkExpDecaySample514(b *testing.B) { 63 benchmarkSample(b, NewExpDecaySample(514, 0.015)) 64 } 65 66 func BenchmarkExpDecaySample1028(b *testing.B) { 67 benchmarkSample(b, NewExpDecaySample(1028, 0.015)) 68 } 69 70 func BenchmarkUniformSample257(b *testing.B) { 71 benchmarkSample(b, NewUniformSample(257)) 72 } 73 74 func BenchmarkUniformSample514(b *testing.B) { 75 benchmarkSample(b, NewUniformSample(514)) 76 } 77 78 func BenchmarkUniformSample1028(b *testing.B) { 79 benchmarkSample(b, NewUniformSample(1028)) 80 } 81 82 func TestExpDecaySample10(t *testing.T) { 83 s := NewExpDecaySample(100, 0.99) 84 for i := 0; i < 10; i++ { 85 s.Update(int64(i)) 86 } 87 if size := s.Count(); size != 10 { 88 t.Errorf("s.Count(): 10 != %v\n", size) 89 } 90 if size := s.Size(); size != 10 { 91 t.Errorf("s.Size(): 10 != %v\n", size) 92 } 93 if l := len(s.Values()); l != 10 { 94 t.Errorf("len(s.Values()): 10 != %v\n", l) 95 } 96 for _, v := range s.Values() { 97 if v > 10 || v < 0 { 98 t.Errorf("out of range [0, 10): %v\n", v) 99 } 100 } 101 } 102 103 func TestExpDecaySample100(t *testing.T) { 104 s := NewExpDecaySample(1000, 0.01) 105 for i := 0; i < 100; i++ { 106 s.Update(int64(i)) 107 } 108 if size := s.Count(); size != 100 { 109 t.Errorf("s.Count(): 100 != %v\n", size) 110 } 111 if size := s.Size(); size != 100 { 112 t.Errorf("s.Size(): 100 != %v\n", size) 113 } 114 if l := len(s.Values()); l != 100 { 115 t.Errorf("len(s.Values()): 100 != %v\n", l) 116 } 117 for _, v := range s.Values() { 118 if v > 100 || v < 0 { 119 t.Errorf("out of range [0, 100): %v\n", v) 120 } 121 } 122 } 123 124 func TestExpDecaySample1000(t *testing.T) { 125 s := NewExpDecaySample(100, 0.99) 126 for i := 0; i < 1000; i++ { 127 s.Update(int64(i)) 128 } 129 if size := s.Count(); size != 1000 { 130 t.Errorf("s.Count(): 1000 != %v\n", size) 131 } 132 if size := s.Size(); size != 100 { 133 t.Errorf("s.Size(): 100 != %v\n", size) 134 } 135 if l := len(s.Values()); l != 100 { 136 t.Errorf("len(s.Values()): 100 != %v\n", l) 137 } 138 for _, v := range s.Values() { 139 if v > 1000 || v < 0 { 140 t.Errorf("out of range [0, 1000): %v\n", v) 141 } 142 } 143 } 144 145 // This test makes sure that the sample's priority is not amplified by using 146 // nanosecond duration since start rather than second duration since start. 147 // The priority becomes +Inf quickly after starting if this is done, 148 // effectively freezing the set of samples until a rescale step happens. 149 func TestExpDecaySampleNanosecondRegression(t *testing.T) { 150 s := NewExpDecaySample(100, 0.99) 151 for i := 0; i < 100; i++ { 152 s.Update(10) 153 } 154 time.Sleep(1 * time.Millisecond) 155 for i := 0; i < 100; i++ { 156 s.Update(20) 157 } 158 v := s.Values() 159 avg := float64(0) 160 for i := 0; i < len(v); i++ { 161 avg += float64(v[i]) 162 } 163 avg /= float64(len(v)) 164 if avg > 16 || avg < 14 { 165 t.Errorf("out of range [14, 16]: %v\n", avg) 166 } 167 } 168 169 func TestExpDecaySampleRescale(t *testing.T) { 170 s := NewExpDecaySample(2, 0.001).(*ExpDecaySample) 171 s.update(time.Now(), 1) 172 s.update(time.Now().Add(time.Hour+time.Microsecond), 1) 173 for _, v := range s.values.Values() { 174 if v.k == 0.0 { 175 t.Fatal("v.k == 0.0") 176 } 177 } 178 } 179 180 func TestExpDecaySampleSnapshot(t *testing.T) { 181 now := time.Now() 182 s := NewExpDecaySample(100, 0.99).(*ExpDecaySample).SetRand(rand.New(rand.NewSource(1))) 183 for i := 1; i <= 10000; i++ { 184 s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) 185 } 186 snapshot := s.Snapshot() 187 s.Update(1) 188 testExpDecaySampleStatistics(t, snapshot) 189 } 190 191 func TestExpDecaySampleStatistics(t *testing.T) { 192 now := time.Now() 193 s := NewExpDecaySample(100, 0.99).(*ExpDecaySample).SetRand(rand.New(rand.NewSource(1))) 194 for i := 1; i <= 10000; i++ { 195 s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) 196 } 197 testExpDecaySampleStatistics(t, s) 198 } 199 200 func TestUniformSample(t *testing.T) { 201 s := NewUniformSample(100) 202 for i := 0; i < 1000; i++ { 203 s.Update(int64(i)) 204 } 205 if size := s.Count(); size != 1000 { 206 t.Errorf("s.Count(): 1000 != %v\n", size) 207 } 208 if size := s.Size(); size != 100 { 209 t.Errorf("s.Size(): 100 != %v\n", size) 210 } 211 if l := len(s.Values()); l != 100 { 212 t.Errorf("len(s.Values()): 100 != %v\n", l) 213 } 214 for _, v := range s.Values() { 215 if v > 1000 || v < 0 { 216 t.Errorf("out of range [0, 100): %v\n", v) 217 } 218 } 219 } 220 221 func TestUniformSampleIncludesTail(t *testing.T) { 222 s := NewUniformSample(100) 223 max := 100 224 for i := 0; i < max; i++ { 225 s.Update(int64(i)) 226 } 227 v := s.Values() 228 sum := 0 229 exp := (max - 1) * max / 2 230 for i := 0; i < len(v); i++ { 231 sum += int(v[i]) 232 } 233 if exp != sum { 234 t.Errorf("sum: %v != %v\n", exp, sum) 235 } 236 } 237 238 func TestUniformSampleSnapshot(t *testing.T) { 239 s := NewUniformSample(100).(*UniformSample).SetRand(rand.New(rand.NewSource(1))) 240 for i := 1; i <= 10000; i++ { 241 s.Update(int64(i)) 242 } 243 snapshot := s.Snapshot() 244 s.Update(1) 245 testUniformSampleStatistics(t, snapshot) 246 } 247 248 func TestUniformSampleStatistics(t *testing.T) { 249 s := NewUniformSample(100).(*UniformSample).SetRand(rand.New(rand.NewSource(1))) 250 for i := 1; i <= 10000; i++ { 251 s.Update(int64(i)) 252 } 253 testUniformSampleStatistics(t, s) 254 } 255 256 func benchmarkSample(b *testing.B, s Sample) { 257 var memStats runtime.MemStats 258 runtime.ReadMemStats(&memStats) 259 pauseTotalNs := memStats.PauseTotalNs 260 b.ResetTimer() 261 for i := 0; i < b.N; i++ { 262 s.Update(1) 263 } 264 b.StopTimer() 265 runtime.GC() 266 runtime.ReadMemStats(&memStats) 267 b.Logf("GC cost: %d ns/op", int(memStats.PauseTotalNs-pauseTotalNs)/b.N) 268 } 269 270 func testExpDecaySampleStatistics(t *testing.T, s Sample) { 271 if count := s.Count(); count != 10000 { 272 t.Errorf("s.Count(): 10000 != %v\n", count) 273 } 274 if min := s.Min(); min != 107 { 275 t.Errorf("s.Min(): 107 != %v\n", min) 276 } 277 if max := s.Max(); max != 10000 { 278 t.Errorf("s.Max(): 10000 != %v\n", max) 279 } 280 if mean := s.Mean(); mean != 4965.98 { 281 t.Errorf("s.Mean(): 4965.98 != %v\n", mean) 282 } 283 if stdDev := s.StdDev(); stdDev != 2959.825156930727 { 284 t.Errorf("s.StdDev(): 2959.825156930727 != %v\n", stdDev) 285 } 286 ps := s.Percentiles([]float64{0.5, 0.75, 0.99}) 287 if ps[0] != 4615 { 288 t.Errorf("median: 4615 != %v\n", ps[0]) 289 } 290 if ps[1] != 7672 { 291 t.Errorf("75th percentile: 7672 != %v\n", ps[1]) 292 } 293 if ps[2] != 9998.99 { 294 t.Errorf("99th percentile: 9998.99 != %v\n", ps[2]) 295 } 296 } 297 298 func testUniformSampleStatistics(t *testing.T, s Sample) { 299 if count := s.Count(); count != 10000 { 300 t.Errorf("s.Count(): 10000 != %v\n", count) 301 } 302 if min := s.Min(); min != 37 { 303 t.Errorf("s.Min(): 37 != %v\n", min) 304 } 305 if max := s.Max(); max != 9989 { 306 t.Errorf("s.Max(): 9989 != %v\n", max) 307 } 308 if mean := s.Mean(); mean != 4748.14 { 309 t.Errorf("s.Mean(): 4748.14 != %v\n", mean) 310 } 311 if stdDev := s.StdDev(); stdDev != 2826.684117548333 { 312 t.Errorf("s.StdDev(): 2826.684117548333 != %v\n", stdDev) 313 } 314 ps := s.Percentiles([]float64{0.5, 0.75, 0.99}) 315 if ps[0] != 4599 { 316 t.Errorf("median: 4599 != %v\n", ps[0]) 317 } 318 if ps[1] != 7380.5 { 319 t.Errorf("75th percentile: 7380.5 != %v\n", ps[1]) 320 } 321 if math.Abs(9986.429999999998-ps[2]) > epsilonPercentile { 322 t.Errorf("99th percentile: 9986.429999999998 != %v\n", ps[2]) 323 } 324 } 325 326 // TestUniformSampleConcurrentUpdateCount would expose data race problems with 327 // concurrent Update and Count calls on Sample when test is called with -race 328 // argument 329 func TestUniformSampleConcurrentUpdateCount(t *testing.T) { 330 if testing.Short() { 331 t.Skip("skipping in short mode") 332 } 333 s := NewUniformSample(100) 334 for i := 0; i < 100; i++ { 335 s.Update(int64(i)) 336 } 337 quit := make(chan struct{}) 338 go func() { 339 t := time.NewTicker(10 * time.Millisecond) 340 defer t.Stop() 341 for { 342 select { 343 case <-t.C: 344 s.Update(rand.Int63()) 345 case <-quit: 346 t.Stop() 347 return 348 } 349 } 350 }() 351 for i := 0; i < 1000; i++ { 352 s.Count() 353 time.Sleep(5 * time.Millisecond) 354 } 355 quit <- struct{}{} 356 }