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