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