package z
import (
"fmt"
"math"
"strings"
"github.com/dustin/go-humanize"
)
func HistogramBounds (minExponent , maxExponent uint32 ) []float64 {
var bounds []float64
for i := minExponent ; i <= maxExponent ; i ++ {
bounds = append (bounds , float64 (int (1 )<<i ))
}
return bounds
}
func Fibonacci (num int ) []float64 {
assert (num > 4 )
bounds := make ([]float64 , num )
bounds [0 ] = 1
bounds [1 ] = 2
for i := 2 ; i < num ; i ++ {
bounds [i ] = bounds [i -1 ] + bounds [i -2 ]
}
return bounds
}
type HistogramData struct {
Bounds []float64
Count int64
CountPerBucket []int64
Min int64
Max int64
Sum int64
}
func NewHistogramData (bounds []float64 ) *HistogramData {
return &HistogramData {
Bounds : bounds ,
CountPerBucket : make ([]int64 , len (bounds )+1 ),
Max : 0 ,
Min : math .MaxInt64 ,
}
}
func (histogram *HistogramData ) Copy () *HistogramData {
if histogram == nil {
return nil
}
return &HistogramData {
Bounds : append ([]float64 {}, histogram .Bounds ...),
CountPerBucket : append ([]int64 {}, histogram .CountPerBucket ...),
Count : histogram .Count ,
Min : histogram .Min ,
Max : histogram .Max ,
Sum : histogram .Sum ,
}
}
func (histogram *HistogramData ) Update (value int64 ) {
if histogram == nil {
return
}
if value > histogram .Max {
histogram .Max = value
}
if value < histogram .Min {
histogram .Min = value
}
histogram .Sum += value
histogram .Count ++
for index := 0 ; index <= len (histogram .Bounds ); index ++ {
if index == len (histogram .Bounds ) {
histogram .CountPerBucket [index ]++
break
}
if value < int64 (histogram .Bounds [index ]) {
histogram .CountPerBucket [index ]++
break
}
}
}
func (histogram *HistogramData ) Mean () float64 {
if histogram .Count == 0 {
return 0
}
return float64 (histogram .Sum ) / float64 (histogram .Count )
}
func (histogram *HistogramData ) String () string {
if histogram == nil {
return ""
}
var b strings .Builder
b .WriteString ("\n -- Histogram: \n" )
b .WriteString (fmt .Sprintf ("Min value: %d \n" , histogram .Min ))
b .WriteString (fmt .Sprintf ("Max value: %d \n" , histogram .Max ))
b .WriteString (fmt .Sprintf ("Count: %d \n" , histogram .Count ))
b .WriteString (fmt .Sprintf ("50p: %.2f \n" , histogram .Percentile (0.5 )))
b .WriteString (fmt .Sprintf ("75p: %.2f \n" , histogram .Percentile (0.75 )))
b .WriteString (fmt .Sprintf ("90p: %.2f \n" , histogram .Percentile (0.90 )))
numBounds := len (histogram .Bounds )
var cum float64
for index , count := range histogram .CountPerBucket {
if count == 0 {
continue
}
if index == len (histogram .CountPerBucket )-1 {
lowerBound := uint64 (histogram .Bounds [numBounds -1 ])
page := float64 (count *100 ) / float64 (histogram .Count )
cum += page
b .WriteString (fmt .Sprintf ("[%s, %s) %d %.2f%% %.2f%%\n" ,
humanize .IBytes (lowerBound ), "infinity" , count , page , cum ))
continue
}
upperBound := uint64 (histogram .Bounds [index ])
lowerBound := uint64 (0 )
if index > 0 {
lowerBound = uint64 (histogram .Bounds [index -1 ])
}
page := float64 (count *100 ) / float64 (histogram .Count )
cum += page
b .WriteString (fmt .Sprintf ("[%d, %d) %d %.2f%% %.2f%%\n" ,
lowerBound , upperBound , count , page , cum ))
}
b .WriteString (" --\n" )
return b .String ()
}
func (histogram *HistogramData ) Percentile (p float64 ) float64 {
if histogram == nil {
return 0
}
if histogram .Count == 0 {
return histogram .Bounds [0 ]
}
pval := int64 (float64 (histogram .Count ) * p )
for i , v := range histogram .CountPerBucket {
pval = pval - v
if pval <= 0 {
if i == len (histogram .Bounds ) {
break
}
return histogram .Bounds [i ]
}
}
return histogram .Bounds [len (histogram .Bounds )-1 ]
}
func (histogram *HistogramData ) Clear () {
if histogram == nil {
return
}
histogram .Count = 0
histogram .CountPerBucket = make ([]int64 , len (histogram .Bounds )+1 )
histogram .Sum = 0
histogram .Max = 0
histogram .Min = math .MaxInt64
}
The pages are generated with Golds v0.8.4 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .