github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/metrics/sample.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:42</date>
    10  //</624342651302318080>
    11  
    12  package metrics
    13  
    14  import (
    15  	"math"
    16  	"math/rand"
    17  	"sort"
    18  	"sync"
    19  	"time"
    20  )
    21  
    22  const rescaleThreshold = time.Hour
    23  
    24  //样本保持统计意义上的值选择
    25  //小溪
    26  type Sample interface {
    27  	Clear()
    28  	Count() int64
    29  	Max() int64
    30  	Mean() float64
    31  	Min() int64
    32  	Percentile(float64) float64
    33  	Percentiles([]float64) []float64
    34  	Size() int
    35  	Snapshot() Sample
    36  	StdDev() float64
    37  	Sum() int64
    38  	Update(int64)
    39  	Values() []int64
    40  	Variance() float64
    41  }
    42  
    43  //expdecaysample是使用正向衰减的指数衰减采样
    44  //优先水库。参见Cormode等人的“前向衰减:一个实际时间”
    45  //流媒体系统的衰减模型”。
    46  //
    47  //<http://dimacs.rutgers.edu/~graham/pubs/papers/fwdecay.pdf>
    48  type ExpDecaySample struct {
    49  	alpha         float64
    50  	count         int64
    51  	mutex         sync.Mutex
    52  	reservoirSize int
    53  	t0, t1        time.Time
    54  	values        *expDecaySampleHeap
    55  }
    56  
    57  //newexpdecaysample使用
    58  //给定储层大小和α。
    59  func NewExpDecaySample(reservoirSize int, alpha float64) Sample {
    60  	if !Enabled {
    61  		return NilSample{}
    62  	}
    63  	s := &ExpDecaySample{
    64  		alpha:         alpha,
    65  		reservoirSize: reservoirSize,
    66  		t0:            time.Now(),
    67  		values:        newExpDecaySampleHeap(reservoirSize),
    68  	}
    69  	s.t1 = s.t0.Add(rescaleThreshold)
    70  	return s
    71  }
    72  
    73  //清除清除所有样本。
    74  func (s *ExpDecaySample) Clear() {
    75  	s.mutex.Lock()
    76  	defer s.mutex.Unlock()
    77  	s.count = 0
    78  	s.t0 = time.Now()
    79  	s.t1 = s.t0.Add(rescaleThreshold)
    80  	s.values.Clear()
    81  }
    82  
    83  //count返回记录的样本数,可能超过
    84  //油藏规模
    85  func (s *ExpDecaySample) Count() int64 {
    86  	s.mutex.Lock()
    87  	defer s.mutex.Unlock()
    88  	return s.count
    89  }
    90  
    91  //max返回样本中的最大值,该值可能不是最大值。
    92  //值永远是样本的一部分。
    93  func (s *ExpDecaySample) Max() int64 {
    94  	return SampleMax(s.Values())
    95  }
    96  
    97  //mean返回样本值的平均值。
    98  func (s *ExpDecaySample) Mean() float64 {
    99  	return SampleMean(s.Values())
   100  }
   101  
   102  //Min返回样本中的最小值,该值可能不是最小值
   103  //值永远是样本的一部分。
   104  func (s *ExpDecaySample) Min() int64 {
   105  	return SampleMin(s.Values())
   106  }
   107  
   108  //Percentile返回样本中任意百分位数的值。
   109  func (s *ExpDecaySample) Percentile(p float64) float64 {
   110  	return SamplePercentile(s.Values(), p)
   111  }
   112  
   113  //Percentiles返回
   114  //样品。
   115  func (s *ExpDecaySample) Percentiles(ps []float64) []float64 {
   116  	return SamplePercentiles(s.Values(), ps)
   117  }
   118  
   119  //SIZE返回样本的大小,最多是储层大小。
   120  func (s *ExpDecaySample) Size() int {
   121  	s.mutex.Lock()
   122  	defer s.mutex.Unlock()
   123  	return s.values.Size()
   124  }
   125  
   126  //快照返回示例的只读副本。
   127  func (s *ExpDecaySample) Snapshot() Sample {
   128  	s.mutex.Lock()
   129  	defer s.mutex.Unlock()
   130  	vals := s.values.Values()
   131  	values := make([]int64, len(vals))
   132  	for i, v := range vals {
   133  		values[i] = v.v
   134  	}
   135  	return &SampleSnapshot{
   136  		count:  s.count,
   137  		values: values,
   138  	}
   139  }
   140  
   141  //stdev返回样本值的标准偏差。
   142  func (s *ExpDecaySample) StdDev() float64 {
   143  	return SampleStdDev(s.Values())
   144  }
   145  
   146  //sum返回样本中值的总和。
   147  func (s *ExpDecaySample) Sum() int64 {
   148  	return SampleSum(s.Values())
   149  }
   150  
   151  //更新示例新值。
   152  func (s *ExpDecaySample) Update(v int64) {
   153  	s.update(time.Now(), v)
   154  }
   155  
   156  //值返回示例中值的副本。
   157  func (s *ExpDecaySample) Values() []int64 {
   158  	s.mutex.Lock()
   159  	defer s.mutex.Unlock()
   160  	vals := s.values.Values()
   161  	values := make([]int64, len(vals))
   162  	for i, v := range vals {
   163  		values[i] = v.v
   164  	}
   165  	return values
   166  }
   167  
   168  //方差返回样本中值的方差。
   169  func (s *ExpDecaySample) Variance() float64 {
   170  	return SampleVariance(s.Values())
   171  }
   172  
   173  //更新在特定时间戳处对新值进行采样。这是一个方法
   174  //它本身有助于测试。
   175  func (s *ExpDecaySample) update(t time.Time, v int64) {
   176  	s.mutex.Lock()
   177  	defer s.mutex.Unlock()
   178  	s.count++
   179  	if s.values.Size() == s.reservoirSize {
   180  		s.values.Pop()
   181  	}
   182  	s.values.Push(expDecaySample{
   183  		k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(),
   184  		v: v,
   185  	})
   186  	if t.After(s.t1) {
   187  		values := s.values.Values()
   188  		t0 := s.t0
   189  		s.values.Clear()
   190  		s.t0 = t
   191  		s.t1 = s.t0.Add(rescaleThreshold)
   192  		for _, v := range values {
   193  			v.k = v.k * math.Exp(-s.alpha*s.t0.Sub(t0).Seconds())
   194  			s.values.Push(v)
   195  		}
   196  	}
   197  }
   198  
   199  //nilsample是一个no op示例。
   200  type NilSample struct{}
   201  
   202  //清除是不可操作的。
   203  func (NilSample) Clear() {}
   204  
   205  //计数是不允许的。
   206  func (NilSample) Count() int64 { return 0 }
   207  
   208  //马克斯不是一个OP。
   209  func (NilSample) Max() int64 { return 0 }
   210  
   211  //平均值是不允许的。
   212  func (NilSample) Mean() float64 { return 0.0 }
   213  
   214  //min是NO-OP。
   215  func (NilSample) Min() int64 { return 0 }
   216  
   217  //百分位数是不允许的。
   218  func (NilSample) Percentile(p float64) float64 { return 0.0 }
   219  
   220  //百分位数是不允许的。
   221  func (NilSample) Percentiles(ps []float64) []float64 {
   222  	return make([]float64, len(ps))
   223  }
   224  
   225  //尺寸是不允许的。
   226  func (NilSample) Size() int { return 0 }
   227  
   228  //样本是不可操作的。
   229  func (NilSample) Snapshot() Sample { return NilSample{} }
   230  
   231  //stdev是一个no-op。
   232  func (NilSample) StdDev() float64 { return 0.0 }
   233  
   234  //和是一个NO-op.
   235  func (NilSample) Sum() int64 { return 0 }
   236  
   237  //更新是不可操作的。
   238  func (NilSample) Update(v int64) {}
   239  
   240  //值是不可操作的。
   241  func (NilSample) Values() []int64 { return []int64{} }
   242  
   243  //方差是不可操作的。
   244  func (NilSample) Variance() float64 { return 0.0 }
   245  
   246  //sampleMax返回Int64切片的最大值。
   247  func SampleMax(values []int64) int64 {
   248  	if 0 == len(values) {
   249  		return 0
   250  	}
   251  	var max int64 = math.MinInt64
   252  	for _, v := range values {
   253  		if max < v {
   254  			max = v
   255  		}
   256  	}
   257  	return max
   258  }
   259  
   260  //samplemean返回Int64切片的平均值。
   261  func SampleMean(values []int64) float64 {
   262  	if 0 == len(values) {
   263  		return 0.0
   264  	}
   265  	return float64(SampleSum(values)) / float64(len(values))
   266  }
   267  
   268  //samplemin返回int64切片的最小值。
   269  func SampleMin(values []int64) int64 {
   270  	if 0 == len(values) {
   271  		return 0
   272  	}
   273  	var min int64 = math.MaxInt64
   274  	for _, v := range values {
   275  		if min > v {
   276  			min = v
   277  		}
   278  	}
   279  	return min
   280  }
   281  
   282  //samplePercentles返回Int64切片的任意百分比。
   283  func SamplePercentile(values int64Slice, p float64) float64 {
   284  	return SamplePercentiles(values, []float64{p})[0]
   285  }
   286  
   287  //samplePercenties返回切片的任意百分比切片
   288  //英特64
   289  func SamplePercentiles(values int64Slice, ps []float64) []float64 {
   290  	scores := make([]float64, len(ps))
   291  	size := len(values)
   292  	if size > 0 {
   293  		sort.Sort(values)
   294  		for i, p := range ps {
   295  			pos := p * float64(size+1)
   296  			if pos < 1.0 {
   297  				scores[i] = float64(values[0])
   298  			} else if pos >= float64(size) {
   299  				scores[i] = float64(values[size-1])
   300  			} else {
   301  				lower := float64(values[int(pos)-1])
   302  				upper := float64(values[int(pos)])
   303  				scores[i] = lower + (pos-math.Floor(pos))*(upper-lower)
   304  			}
   305  		}
   306  	}
   307  	return scores
   308  }
   309  
   310  //samplesnapshot是另一个示例的只读副本。
   311  type SampleSnapshot struct {
   312  	count  int64
   313  	values []int64
   314  }
   315  
   316  func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot {
   317  	return &SampleSnapshot{
   318  		count:  count,
   319  		values: values,
   320  	}
   321  }
   322  
   323  //清晰的恐慌。
   324  func (*SampleSnapshot) Clear() {
   325  	panic("Clear called on a SampleSnapshot")
   326  }
   327  
   328  //Count返回拍摄快照时的输入计数。
   329  func (s *SampleSnapshot) Count() int64 { return s.count }
   330  
   331  //max返回快照拍摄时的最大值。
   332  func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) }
   333  
   334  //mean返回拍摄快照时的平均值。
   335  func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) }
   336  
   337  //Min返回拍摄快照时的最小值。
   338  func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) }
   339  
   340  //percentile返回在
   341  //已拍摄快照。
   342  func (s *SampleSnapshot) Percentile(p float64) float64 {
   343  	return SamplePercentile(s.values, p)
   344  }
   345  
   346  //Percentiles返回当时任意百分位值的切片
   347  //快照已拍摄。
   348  func (s *SampleSnapshot) Percentiles(ps []float64) []float64 {
   349  	return SamplePercentiles(s.values, ps)
   350  }
   351  
   352  //SIZE返回拍摄快照时样本的大小。
   353  func (s *SampleSnapshot) Size() int { return len(s.values) }
   354  
   355  //快照返回快照。
   356  func (s *SampleSnapshot) Snapshot() Sample { return s }
   357  
   358  //stdev返回快照时值的标准偏差
   359  //拿。
   360  func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) }
   361  
   362  //SUM返回拍摄快照时的值总和。
   363  func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) }
   364  
   365  //更新恐慌。
   366  func (*SampleSnapshot) Update(int64) {
   367  	panic("Update called on a SampleSnapshot")
   368  }
   369  
   370  //值返回示例中值的副本。
   371  func (s *SampleSnapshot) Values() []int64 {
   372  	values := make([]int64, len(s.values))
   373  	copy(values, s.values)
   374  	return values
   375  }
   376  
   377  //variance返回拍摄快照时值的方差。
   378  func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) }
   379  
   380  //samplestdev返回int64切片的标准偏差。
   381  func SampleStdDev(values []int64) float64 {
   382  	return math.Sqrt(SampleVariance(values))
   383  }
   384  
   385  //samplesum返回Int64切片的和。
   386  func SampleSum(values []int64) int64 {
   387  	var sum int64
   388  	for _, v := range values {
   389  		sum += v
   390  	}
   391  	return sum
   392  }
   393  
   394  //samplevariance返回Int64切片的方差。
   395  func SampleVariance(values []int64) float64 {
   396  	if 0 == len(values) {
   397  		return 0.0
   398  	}
   399  	m := SampleMean(values)
   400  	var sum float64
   401  	for _, v := range values {
   402  		d := float64(v) - m
   403  		sum += d * d
   404  	}
   405  	return sum / float64(len(values))
   406  }
   407  
   408  //使用维特算法R的均匀样本。
   409  //
   410  //<http://www.cs.umd.edu/~samir/498/vitter.pdf>
   411  type UniformSample struct {
   412  	count         int64
   413  	mutex         sync.Mutex
   414  	reservoirSize int
   415  	values        []int64
   416  }
   417  
   418  //NewUniformSample构造一个新的具有给定储层的均匀样品
   419  //尺寸。
   420  func NewUniformSample(reservoirSize int) Sample {
   421  	if !Enabled {
   422  		return NilSample{}
   423  	}
   424  	return &UniformSample{
   425  		reservoirSize: reservoirSize,
   426  		values:        make([]int64, 0, reservoirSize),
   427  	}
   428  }
   429  
   430  //清除清除所有样本。
   431  func (s *UniformSample) Clear() {
   432  	s.mutex.Lock()
   433  	defer s.mutex.Unlock()
   434  	s.count = 0
   435  	s.values = make([]int64, 0, s.reservoirSize)
   436  }
   437  
   438  //count返回记录的样本数,可能超过
   439  //油藏规模
   440  func (s *UniformSample) Count() int64 {
   441  	s.mutex.Lock()
   442  	defer s.mutex.Unlock()
   443  	return s.count
   444  }
   445  
   446  //max返回样本中的最大值,该值可能不是最大值。
   447  //值永远是样本的一部分。
   448  func (s *UniformSample) Max() int64 {
   449  	s.mutex.Lock()
   450  	defer s.mutex.Unlock()
   451  	return SampleMax(s.values)
   452  }
   453  
   454  //mean返回样本值的平均值。
   455  func (s *UniformSample) Mean() float64 {
   456  	s.mutex.Lock()
   457  	defer s.mutex.Unlock()
   458  	return SampleMean(s.values)
   459  }
   460  
   461  //Min返回样本中的最小值,该值可能不是最小值
   462  //值永远是样本的一部分。
   463  func (s *UniformSample) Min() int64 {
   464  	s.mutex.Lock()
   465  	defer s.mutex.Unlock()
   466  	return SampleMin(s.values)
   467  }
   468  
   469  //Percentile返回样本中任意百分位数的值。
   470  func (s *UniformSample) Percentile(p float64) float64 {
   471  	s.mutex.Lock()
   472  	defer s.mutex.Unlock()
   473  	return SamplePercentile(s.values, p)
   474  }
   475  
   476  //Percentiles返回
   477  //样品。
   478  func (s *UniformSample) Percentiles(ps []float64) []float64 {
   479  	s.mutex.Lock()
   480  	defer s.mutex.Unlock()
   481  	return SamplePercentiles(s.values, ps)
   482  }
   483  
   484  //SIZE返回样本的大小,最多是储层大小。
   485  func (s *UniformSample) Size() int {
   486  	s.mutex.Lock()
   487  	defer s.mutex.Unlock()
   488  	return len(s.values)
   489  }
   490  
   491  //快照返回示例的只读副本。
   492  func (s *UniformSample) Snapshot() Sample {
   493  	s.mutex.Lock()
   494  	defer s.mutex.Unlock()
   495  	values := make([]int64, len(s.values))
   496  	copy(values, s.values)
   497  	return &SampleSnapshot{
   498  		count:  s.count,
   499  		values: values,
   500  	}
   501  }
   502  
   503  //stdev返回样本值的标准偏差。
   504  func (s *UniformSample) StdDev() float64 {
   505  	s.mutex.Lock()
   506  	defer s.mutex.Unlock()
   507  	return SampleStdDev(s.values)
   508  }
   509  
   510  //sum返回样本中值的总和。
   511  func (s *UniformSample) Sum() int64 {
   512  	s.mutex.Lock()
   513  	defer s.mutex.Unlock()
   514  	return SampleSum(s.values)
   515  }
   516  
   517  //更新示例新值。
   518  func (s *UniformSample) Update(v int64) {
   519  	s.mutex.Lock()
   520  	defer s.mutex.Unlock()
   521  	s.count++
   522  	if len(s.values) < s.reservoirSize {
   523  		s.values = append(s.values, v)
   524  	} else {
   525  		r := rand.Int63n(s.count)
   526  		if r < int64(len(s.values)) {
   527  			s.values[int(r)] = v
   528  		}
   529  	}
   530  }
   531  
   532  //值返回示例中值的副本。
   533  func (s *UniformSample) Values() []int64 {
   534  	s.mutex.Lock()
   535  	defer s.mutex.Unlock()
   536  	values := make([]int64, len(s.values))
   537  	copy(values, s.values)
   538  	return values
   539  }
   540  
   541  //方差返回样本中值的方差。
   542  func (s *UniformSample) Variance() float64 {
   543  	s.mutex.Lock()
   544  	defer s.mutex.Unlock()
   545  	return SampleVariance(s.values)
   546  }
   547  
   548  //expdecaysample表示堆中的单个样本。
   549  type expDecaySample struct {
   550  	k float64
   551  	v int64
   552  }
   553  
   554  func newExpDecaySampleHeap(reservoirSize int) *expDecaySampleHeap {
   555  	return &expDecaySampleHeap{make([]expDecaySample, 0, reservoirSize)}
   556  }
   557  
   558  //expdecaysampleheap是expdecaysamples的最小堆。
   559  //从标准库的容器/堆复制内部实现
   560  type expDecaySampleHeap struct {
   561  	s []expDecaySample
   562  }
   563  
   564  func (h *expDecaySampleHeap) Clear() {
   565  	h.s = h.s[:0]
   566  }
   567  
   568  func (h *expDecaySampleHeap) Push(s expDecaySample) {
   569  	n := len(h.s)
   570  	h.s = h.s[0 : n+1]
   571  	h.s[n] = s
   572  	h.up(n)
   573  }
   574  
   575  func (h *expDecaySampleHeap) Pop() expDecaySample {
   576  	n := len(h.s) - 1
   577  	h.s[0], h.s[n] = h.s[n], h.s[0]
   578  	h.down(0, n)
   579  
   580  	n = len(h.s)
   581  	s := h.s[n-1]
   582  	h.s = h.s[0 : n-1]
   583  	return s
   584  }
   585  
   586  func (h *expDecaySampleHeap) Size() int {
   587  	return len(h.s)
   588  }
   589  
   590  func (h *expDecaySampleHeap) Values() []expDecaySample {
   591  	return h.s
   592  }
   593  
   594  func (h *expDecaySampleHeap) up(j int) {
   595  	for {
   596  i := (j - 1) / 2 //起源
   597  		if i == j || !(h.s[j].k < h.s[i].k) {
   598  			break
   599  		}
   600  		h.s[i], h.s[j] = h.s[j], h.s[i]
   601  		j = i
   602  	}
   603  }
   604  
   605  func (h *expDecaySampleHeap) down(i, n int) {
   606  	for {
   607  		j1 := 2*i + 1
   608  if j1 >= n || j1 < 0 { //int溢出后j1<0
   609  			break
   610  		}
   611  j := j1 //留守儿童
   612  		if j2 := j1 + 1; j2 < n && !(h.s[j1].k < h.s[j2].k) {
   613  j = j2 //=2*i+2//右儿童
   614  		}
   615  		if !(h.s[j].k < h.s[i].k) {
   616  			break
   617  		}
   618  		h.s[i], h.s[j] = h.s[j], h.s[i]
   619  		i = j
   620  	}
   621  }
   622  
   623  type int64Slice []int64
   624  
   625  func (p int64Slice) Len() int           { return len(p) }
   626  func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] }
   627  func (p int64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
   628