github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/metrics/sample_test.go (about)

     1  package metrics
     2  
     3  import (
     4  	"math/rand"
     5  	"runtime"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func BenchmarkCompute1000(b *testing.B) {
    11  	s := make([]int64, 1000)
    12  	for i := 0; i < len(s); i++ {
    13  		s[i] = int64(i)
    14  	}
    15  	b.ResetTimer()
    16  	for i := 0; i < b.N; i++ {
    17  		SampleVariance(s)
    18  	}
    19  }
    20  func BenchmarkCompute1000000(b *testing.B) {
    21  	s := make([]int64, 1000000)
    22  	for i := 0; i < len(s); i++ {
    23  		s[i] = int64(i)
    24  	}
    25  	b.ResetTimer()
    26  	for i := 0; i < b.N; i++ {
    27  		SampleVariance(s)
    28  	}
    29  }
    30  func BenchmarkCopy1000(b *testing.B) {
    31  	s := make([]int64, 1000)
    32  	for i := 0; i < len(s); i++ {
    33  		s[i] = int64(i)
    34  	}
    35  	b.ResetTimer()
    36  	for i := 0; i < b.N; i++ {
    37  		sCopy := make([]int64, len(s))
    38  		copy(sCopy, s)
    39  	}
    40  }
    41  func BenchmarkCopy1000000(b *testing.B) {
    42  	s := make([]int64, 1000000)
    43  	for i := 0; i < len(s); i++ {
    44  		s[i] = int64(i)
    45  	}
    46  	b.ResetTimer()
    47  	for i := 0; i < b.N; i++ {
    48  		sCopy := make([]int64, len(s))
    49  		copy(sCopy, s)
    50  	}
    51  }
    52  
    53  func BenchmarkExpDecaySample257(b *testing.B) {
    54  	benchmarkSample(b, NewExpDecaySample(257, 0.015))
    55  }
    56  
    57  func BenchmarkExpDecaySample514(b *testing.B) {
    58  	benchmarkSample(b, NewExpDecaySample(514, 0.015))
    59  }
    60  
    61  func BenchmarkExpDecaySample1028(b *testing.B) {
    62  	benchmarkSample(b, NewExpDecaySample(1028, 0.015))
    63  }
    64  
    65  func BenchmarkUniformSample257(b *testing.B) {
    66  	benchmarkSample(b, NewUniformSample(257))
    67  }
    68  
    69  func BenchmarkUniformSample514(b *testing.B) {
    70  	benchmarkSample(b, NewUniformSample(514))
    71  }
    72  
    73  func BenchmarkUniformSample1028(b *testing.B) {
    74  	benchmarkSample(b, NewUniformSample(1028))
    75  }
    76  
    77  func TestExpDecaySample10(t *testing.T) {
    78  	rand.Seed(1)
    79  	s := NewExpDecaySample(100, 0.99)
    80  	for i := 0; i < 10; i++ {
    81  		s.Update(int64(i))
    82  	}
    83  	if size := s.Count(); 10 != size {
    84  		t.Errorf("s.Count(): 10 != %v\n", size)
    85  	}
    86  	if size := s.Size(); 10 != size {
    87  		t.Errorf("s.Size(): 10 != %v\n", size)
    88  	}
    89  	if l := len(s.Values()); 10 != l {
    90  		t.Errorf("len(s.Values()): 10 != %v\n", l)
    91  	}
    92  	for _, v := range s.Values() {
    93  		if v > 10 || v < 0 {
    94  			t.Errorf("out of range [0, 10): %v\n", v)
    95  		}
    96  	}
    97  }
    98  
    99  func TestExpDecaySample100(t *testing.T) {
   100  	rand.Seed(1)
   101  	s := NewExpDecaySample(1000, 0.01)
   102  	for i := 0; i < 100; i++ {
   103  		s.Update(int64(i))
   104  	}
   105  	if size := s.Count(); 100 != size {
   106  		t.Errorf("s.Count(): 100 != %v\n", size)
   107  	}
   108  	if size := s.Size(); 100 != size {
   109  		t.Errorf("s.Size(): 100 != %v\n", size)
   110  	}
   111  	if l := len(s.Values()); 100 != l {
   112  		t.Errorf("len(s.Values()): 100 != %v\n", l)
   113  	}
   114  	for _, v := range s.Values() {
   115  		if v > 100 || v < 0 {
   116  			t.Errorf("out of range [0, 100): %v\n", v)
   117  		}
   118  	}
   119  }
   120  
   121  func TestExpDecaySample1000(t *testing.T) {
   122  	rand.Seed(1)
   123  	s := NewExpDecaySample(100, 0.99)
   124  	for i := 0; i < 1000; i++ {
   125  		s.Update(int64(i))
   126  	}
   127  	if size := s.Count(); 1000 != size {
   128  		t.Errorf("s.Count(): 1000 != %v\n", size)
   129  	}
   130  	if size := s.Size(); 100 != size {
   131  		t.Errorf("s.Size(): 100 != %v\n", size)
   132  	}
   133  	if l := len(s.Values()); 100 != l {
   134  		t.Errorf("len(s.Values()): 100 != %v\n", l)
   135  	}
   136  	for _, v := range s.Values() {
   137  		if v > 1000 || v < 0 {
   138  			t.Errorf("out of range [0, 1000): %v\n", v)
   139  		}
   140  	}
   141  }
   142  
   143  func TestExpDecaySampleNanosecondRegression(t *testing.T) {
   144  	rand.Seed(1)
   145  	s := NewExpDecaySample(100, 0.99)
   146  	for i := 0; i < 100; i++ {
   147  		s.Update(10)
   148  	}
   149  	time.Sleep(1 * time.Millisecond)
   150  	for i := 0; i < 100; i++ {
   151  		s.Update(20)
   152  	}
   153  	v := s.Values()
   154  	avg := float64(0)
   155  	for i := 0; i < len(v); i++ {
   156  		avg += float64(v[i])
   157  	}
   158  	avg /= float64(len(v))
   159  	if avg > 16 || avg < 14 {
   160  		t.Errorf("out of range [14, 16]: %v\n", avg)
   161  	}
   162  }
   163  
   164  func TestExpDecaySampleRescale(t *testing.T) {
   165  	s := NewExpDecaySample(2, 0.001).(*ExpDecaySample)
   166  	s.update(time.Now(), 1)
   167  	s.update(time.Now().Add(time.Hour+time.Microsecond), 1)
   168  	for _, v := range s.values.Values() {
   169  		if v.k == 0.0 {
   170  			t.Fatal("v.k == 0.0")
   171  		}
   172  	}
   173  }
   174  
   175  func TestExpDecaySampleSnapshot(t *testing.T) {
   176  	now := time.Now()
   177  	rand.Seed(1)
   178  	s := NewExpDecaySample(100, 0.99)
   179  	for i := 1; i <= 10000; i++ {
   180  		s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i))
   181  	}
   182  	snapshot := s.Snapshot()
   183  	s.Update(1)
   184  	testExpDecaySampleStatistics(t, snapshot)
   185  }
   186  
   187  func TestExpDecaySampleStatistics(t *testing.T) {
   188  	now := time.Now()
   189  	rand.Seed(1)
   190  	s := NewExpDecaySample(100, 0.99)
   191  	for i := 1; i <= 10000; i++ {
   192  		s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i))
   193  	}
   194  	testExpDecaySampleStatistics(t, s)
   195  }
   196  
   197  func TestUniformSample(t *testing.T) {
   198  	rand.Seed(1)
   199  	s := NewUniformSample(100)
   200  	for i := 0; i < 1000; i++ {
   201  		s.Update(int64(i))
   202  	}
   203  	if size := s.Count(); 1000 != size {
   204  		t.Errorf("s.Count(): 1000 != %v\n", size)
   205  	}
   206  	if size := s.Size(); 100 != size {
   207  		t.Errorf("s.Size(): 100 != %v\n", size)
   208  	}
   209  	if l := len(s.Values()); 100 != l {
   210  		t.Errorf("len(s.Values()): 100 != %v\n", l)
   211  	}
   212  	for _, v := range s.Values() {
   213  		if v > 1000 || v < 0 {
   214  			t.Errorf("out of range [0, 100): %v\n", v)
   215  		}
   216  	}
   217  }
   218  
   219  func TestUniformSampleIncludesTail(t *testing.T) {
   220  	rand.Seed(1)
   221  	s := NewUniformSample(100)
   222  	max := 100
   223  	for i := 0; i < max; i++ {
   224  		s.Update(int64(i))
   225  	}
   226  	v := s.Values()
   227  	sum := 0
   228  	exp := (max - 1) * max / 2
   229  	for i := 0; i < len(v); i++ {
   230  		sum += int(v[i])
   231  	}
   232  	if exp != sum {
   233  		t.Errorf("sum: %v != %v\n", exp, sum)
   234  	}
   235  }
   236  
   237  func TestUniformSampleSnapshot(t *testing.T) {
   238  	s := NewUniformSample(100)
   239  	for i := 1; i <= 10000; i++ {
   240  		s.Update(int64(i))
   241  	}
   242  	snapshot := s.Snapshot()
   243  	s.Update(1)
   244  	testUniformSampleStatistics(t, snapshot)
   245  }
   246  
   247  func TestUniformSampleStatistics(t *testing.T) {
   248  	rand.Seed(1)
   249  	s := NewUniformSample(100)
   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(); 10000 != count {
   272  		t.Errorf("s.Count(): 10000 != %v\n", count)
   273  	}
   274  	if min := s.Min(); 107 != min {
   275  		t.Errorf("s.Min(): 107 != %v\n", min)
   276  	}
   277  	if max := s.Max(); 10000 != max {
   278  		t.Errorf("s.Max(): 10000 != %v\n", max)
   279  	}
   280  	if mean := s.Mean(); 4965.98 != mean {
   281  		t.Errorf("s.Mean(): 4965.98 != %v\n", mean)
   282  	}
   283  	if stdDev := s.StdDev(); 2959.825156930727 != stdDev {
   284  		t.Errorf("s.StdDev(): 2959.825156930727 != %v\n", stdDev)
   285  	}
   286  	ps := s.Percentiles([]float64{0.5, 0.75, 0.99})
   287  	if 4615 != ps[0] {
   288  		t.Errorf("median: 4615 != %v\n", ps[0])
   289  	}
   290  	if 7672 != ps[1] {
   291  		t.Errorf("75th percentile: 7672 != %v\n", ps[1])
   292  	}
   293  	if 9998.99 != ps[2] {
   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(); 10000 != count {
   300  		t.Errorf("s.Count(): 10000 != %v\n", count)
   301  	}
   302  	if min := s.Min(); 37 != min {
   303  		t.Errorf("s.Min(): 37 != %v\n", min)
   304  	}
   305  	if max := s.Max(); 9989 != max {
   306  		t.Errorf("s.Max(): 9989 != %v\n", max)
   307  	}
   308  	if mean := s.Mean(); 4748.14 != mean {
   309  		t.Errorf("s.Mean(): 4748.14 != %v\n", mean)
   310  	}
   311  	if stdDev := s.StdDev(); 2826.684117548333 != stdDev {
   312  		t.Errorf("s.StdDev(): 2826.684117548333 != %v\n", stdDev)
   313  	}
   314  	ps := s.Percentiles([]float64{0.5, 0.75, 0.99})
   315  	if 4599 != ps[0] {
   316  		t.Errorf("median: 4599 != %v\n", ps[0])
   317  	}
   318  	if 7380.5 != ps[1] {
   319  		t.Errorf("75th percentile: 7380.5 != %v\n", ps[1])
   320  	}
   321  	if 9986.429999999998 != ps[2] {
   322  		t.Errorf("99th percentile: 9986.429999999998 != %v\n", ps[2])
   323  	}
   324  }
   325  
   326  func TestUniformSampleConcurrentUpdateCount(t *testing.T) {
   327  	if testing.Short() {
   328  		t.Skip("skipping in short mode")
   329  	}
   330  	s := NewUniformSample(100)
   331  	for i := 0; i < 100; i++ {
   332  		s.Update(int64(i))
   333  	}
   334  	quit := make(chan struct{})
   335  	go func() {
   336  		t := time.NewTicker(10 * time.Millisecond)
   337  		for {
   338  			select {
   339  			case <-t.C:
   340  				s.Update(rand.Int63())
   341  			case <-quit:
   342  				t.Stop()
   343  				return
   344  			}
   345  		}
   346  	}()
   347  	for i := 0; i < 1000; i++ {
   348  		s.Count()
   349  		time.Sleep(5 * time.Millisecond)
   350  	}
   351  	quit <- struct{}{}
   352  }