diff options
Diffstat (limited to 'vendor/github.com/vbauerster/mpb/decor/speed.go')
-rw-r--r-- | vendor/github.com/vbauerster/mpb/decor/speed.go | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/vendor/github.com/vbauerster/mpb/decor/speed.go b/vendor/github.com/vbauerster/mpb/decor/speed.go new file mode 100644 index 000000000..395e5d04d --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/decor/speed.go @@ -0,0 +1,270 @@ +package decor + +import ( + "fmt" + "io" + "math" + "strconv" + "strings" + "time" + + "github.com/VividCortex/ewma" +) + +type SpeedKiB float64 + +func (s SpeedKiB) Format(st fmt.State, verb rune) { + prec, ok := st.Precision() + + if verb == 'd' || !ok { + prec = 0 + } + if verb == 'f' && !ok { + prec = 6 + } + // retain old beahavior if s verb used + if verb == 's' { + prec = 1 + } + + var res, unit string + switch { + case s >= TiB: + unit = "TiB/s" + res = strconv.FormatFloat(float64(s)/TiB, 'f', prec, 64) + case s >= GiB: + unit = "GiB/s" + res = strconv.FormatFloat(float64(s)/GiB, 'f', prec, 64) + case s >= MiB: + unit = "MiB/s" + res = strconv.FormatFloat(float64(s)/MiB, 'f', prec, 64) + case s >= KiB: + unit = "KiB/s" + res = strconv.FormatFloat(float64(s)/KiB, 'f', prec, 64) + default: + unit = "b/s" + res = strconv.FormatInt(int64(s), 10) + } + + if st.Flag(' ') { + res += " " + } + res += unit + + if w, ok := st.Width(); ok { + if len(res) < w { + pad := strings.Repeat(" ", w-len(res)) + if st.Flag(int('-')) { + res += pad + } else { + res = pad + res + } + } + } + + io.WriteString(st, res) +} + +type SpeedKB float64 + +func (s SpeedKB) Format(st fmt.State, verb rune) { + prec, ok := st.Precision() + + if verb == 'd' || !ok { + prec = 0 + } + if verb == 'f' && !ok { + prec = 6 + } + // retain old beahavior if s verb used + if verb == 's' { + prec = 1 + } + + var res, unit string + switch { + case s >= TB: + unit = "TB/s" + res = strconv.FormatFloat(float64(s)/TB, 'f', prec, 64) + case s >= GB: + unit = "GB/s" + res = strconv.FormatFloat(float64(s)/GB, 'f', prec, 64) + case s >= MB: + unit = "MB/s" + res = strconv.FormatFloat(float64(s)/MB, 'f', prec, 64) + case s >= KB: + unit = "kB/s" + res = strconv.FormatFloat(float64(s)/KB, 'f', prec, 64) + default: + unit = "b/s" + res = strconv.FormatInt(int64(s), 10) + } + + if st.Flag(' ') { + res += " " + } + res += unit + + if w, ok := st.Width(); ok { + if len(res) < w { + pad := strings.Repeat(" ", w-len(res)) + if st.Flag(int('-')) { + res += pad + } else { + res = pad + res + } + } + } + + io.WriteString(st, res) +} + +// EwmaSpeed exponential-weighted-moving-average based speed decorator, +// with dynamic unit measure adjustment. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `unitFormat` printf compatible verb for value, like "%f" or "%d" +// +// `average` MovingAverage implementation +// +// `wcc` optional WC config +// +// unitFormat example if UnitKiB is chosen: +// +// "%.1f" = "1.0MiB/s" or "% .1f" = "1.0 MiB/s" +func EwmaSpeed(unit int, unitFormat string, age float64, wcc ...WC) Decorator { + return MovingAverageSpeed(unit, unitFormat, ewma.NewMovingAverage(age), wcc...) +} + +// MovingAverageSpeed decorator relies on MovingAverage implementation to calculate its average. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `unitFormat` printf compatible verb for value, like "%f" or "%d" +// +// `average` MovingAverage implementation +// +// `wcc` optional WC config +func MovingAverageSpeed(unit int, unitFormat string, average MovingAverage, wcc ...WC) Decorator { + var wc WC + for _, widthConf := range wcc { + wc = widthConf + } + wc.Init() + d := &movingAverageSpeed{ + WC: wc, + unit: unit, + unitFormat: unitFormat, + average: average, + } + return d +} + +type movingAverageSpeed struct { + WC + unit int + unitFormat string + average ewma.MovingAverage + msg string + completeMsg *string +} + +func (d *movingAverageSpeed) Decor(st *Statistics) string { + if st.Completed { + if d.completeMsg != nil { + return d.FormatMsg(*d.completeMsg) + } + return d.FormatMsg(d.msg) + } + + speed := d.average.Value() + switch d.unit { + case UnitKiB: + d.msg = fmt.Sprintf(d.unitFormat, SpeedKiB(speed)) + case UnitKB: + d.msg = fmt.Sprintf(d.unitFormat, SpeedKB(speed)) + default: + d.msg = fmt.Sprintf(d.unitFormat, speed) + } + + return d.FormatMsg(d.msg) +} + +func (s *movingAverageSpeed) NextAmount(n int, wdd ...time.Duration) { + var workDuration time.Duration + for _, wd := range wdd { + workDuration = wd + } + speed := float64(n) / workDuration.Seconds() / 1000 + if math.IsInf(speed, 0) || math.IsNaN(speed) { + return + } + s.average.Add(speed) +} + +func (d *movingAverageSpeed) OnCompleteMessage(msg string) { + d.completeMsg = &msg +} + +// AverageSpeed decorator with dynamic unit measure adjustment. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `unitFormat` printf compatible verb for value, like "%f" or "%d" +// +// `wcc` optional WC config +// +// unitFormat example if UnitKiB is chosen: +// +// "%.1f" = "1.0MiB/s" or "% .1f" = "1.0 MiB/s" +func AverageSpeed(unit int, unitFormat string, wcc ...WC) Decorator { + var wc WC + for _, widthConf := range wcc { + wc = widthConf + } + wc.Init() + d := &averageSpeed{ + WC: wc, + unit: unit, + unitFormat: unitFormat, + startTime: time.Now(), + } + return d +} + +type averageSpeed struct { + WC + unit int + unitFormat string + startTime time.Time + msg string + completeMsg *string +} + +func (d *averageSpeed) Decor(st *Statistics) string { + if st.Completed { + if d.completeMsg != nil { + return d.FormatMsg(*d.completeMsg) + } + return d.FormatMsg(d.msg) + } + + timeElapsed := time.Since(d.startTime) + speed := float64(st.Current) / timeElapsed.Seconds() + + switch d.unit { + case UnitKiB: + d.msg = fmt.Sprintf(d.unitFormat, SpeedKiB(speed)) + case UnitKB: + d.msg = fmt.Sprintf(d.unitFormat, SpeedKB(speed)) + default: + d.msg = fmt.Sprintf(d.unitFormat, speed) + } + + return d.FormatMsg(d.msg) +} + +func (d *averageSpeed) OnCompleteMessage(msg string) { + d.completeMsg = &msg +} |