github.com/MaynardMiner/ethereumprogpow@v1.8.23/metrics/sample_test.go (about)

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