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  }