From 852e40c5bc832527780e31a3af738bf559aeb1d6 Mon Sep 17 00:00:00 2001 From: Kevin Minehart Date: Tue, 26 Jan 2021 11:47:33 -0600 Subject: [PATCH 1/3] Move some utility functions out of `util` and into their own packages (#3734) * separate out some util packages Signed-off-by: Kevin Minehart * use goimports with -local Signed-off-by: Kevin Minehart * refactor: reduce the number of transitive imports when using math and logging functions Signed-off-by: Kevin Minehart * add deprecation warning to pkg/log/log.go Signed-off-by: Kevin Minehart --- pkg/util/math/math.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 pkg/util/math/math.go diff --git a/pkg/util/math/math.go b/pkg/util/math/math.go new file mode 100644 index 000000000..01e544384 --- /dev/null +++ b/pkg/util/math/math.go @@ -0,0 +1,33 @@ +package math + +// Max returns the maximum of two ints +func Max(a, b int) int { + if a > b { + return a + } + return b +} + +// Min returns the minimum of two ints +func Min(a, b int) int { + if a < b { + return a + } + return b +} + +// Max64 returns the maximum of two int64s +func Max64(a, b int64) int64 { + if a > b { + return a + } + return b +} + +// Min64 returns the minimum of two int64s +func Min64(a, b int64) int64 { + if a < b { + return a + } + return b +} From c4582720dbe6ae45d285b8bb8eed867f9807c620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C5=A0tibran=C3=BD?= Date: Mon, 12 Apr 2021 14:13:06 +0200 Subject: [PATCH 2/3] Move ewmaRate into util/math package, and make it public. (#4070) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move ewmaRate into util/math package, and make it public. Signed-off-by: Peter Štibraný * Use util_math import name. Signed-off-by: Peter Štibraný * Fix double import. Signed-off-by: Peter Štibraný --- pkg/util/math/rate.go | 59 ++++++++++++++++++++++++++++++++++++++ pkg/util/math/rate_test.go | 47 ++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 pkg/util/math/rate.go create mode 100644 pkg/util/math/rate_test.go diff --git a/pkg/util/math/rate.go b/pkg/util/math/rate.go new file mode 100644 index 000000000..19bbe6428 --- /dev/null +++ b/pkg/util/math/rate.go @@ -0,0 +1,59 @@ +package math + +import ( + "sync" + "time" + + "go.uber.org/atomic" +) + +// EwmaRate tracks an exponentially weighted moving average of a per-second rate. +type EwmaRate struct { + newEvents atomic.Int64 + + alpha float64 + interval time.Duration + + mutex sync.RWMutex + lastRate float64 + init bool +} + +func NewEWMARate(alpha float64, interval time.Duration) *EwmaRate { + return &EwmaRate{ + alpha: alpha, + interval: interval, + } +} + +// Rate returns the per-second rate. +func (r *EwmaRate) Rate() float64 { + r.mutex.RLock() + defer r.mutex.RUnlock() + return r.lastRate +} + +// Tick assumes to be called every r.interval. +func (r *EwmaRate) Tick() { + newEvents := r.newEvents.Swap(0) + instantRate := float64(newEvents) / r.interval.Seconds() + + r.mutex.Lock() + defer r.mutex.Unlock() + + if r.init { + r.lastRate += r.alpha * (instantRate - r.lastRate) + } else { + r.init = true + r.lastRate = instantRate + } +} + +// Inc counts one event. +func (r *EwmaRate) Inc() { + r.newEvents.Inc() +} + +func (r *EwmaRate) Add(delta int64) { + r.newEvents.Add(delta) +} diff --git a/pkg/util/math/rate_test.go b/pkg/util/math/rate_test.go new file mode 100644 index 000000000..378180caa --- /dev/null +++ b/pkg/util/math/rate_test.go @@ -0,0 +1,47 @@ +package math + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestRate(t *testing.T) { + ticks := []struct { + events int + want float64 + }{ + {60, 1}, + {30, 0.9}, + {0, 0.72}, + {60, 0.776}, + {0, 0.6208}, + {0, 0.49664}, + {0, 0.397312}, + {0, 0.3178496}, + {0, 0.25427968}, + {0, 0.203423744}, + {0, 0.1627389952}, + } + r := NewEWMARate(0.2, time.Minute) + + for _, tick := range ticks { + for e := 0; e < tick.events; e++ { + r.Inc() + } + r.Tick() + // We cannot do double comparison, because double operations on different + // platforms may actually produce results that differ slightly. + // There are multiple issues about this in Go's github, eg: 18354 or 20319. + require.InDelta(t, tick.want, r.Rate(), 0.0000000001, "unexpected rate") + } + + r = NewEWMARate(0.2, time.Minute) + + for _, tick := range ticks { + r.Add(int64(tick.events)) + r.Tick() + require.InDelta(t, tick.want, r.Rate(), 0.0000000001, "unexpected rate") + } +} From 371324011b0452515eecd99c2ddacd94076f7fb0 Mon Sep 17 00:00:00 2001 From: Tyler Reid Date: Thu, 2 Sep 2021 13:37:55 -0500 Subject: [PATCH 3/3] Move math to the top level directory for use Signed-off-by: Tyler Reid --- {pkg/util/math => math}/math.go | 0 {pkg/util/math => math}/rate.go | 0 {pkg/util/math => math}/rate_test.go | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {pkg/util/math => math}/math.go (100%) rename {pkg/util/math => math}/rate.go (100%) rename {pkg/util/math => math}/rate_test.go (100%) diff --git a/pkg/util/math/math.go b/math/math.go similarity index 100% rename from pkg/util/math/math.go rename to math/math.go diff --git a/pkg/util/math/rate.go b/math/rate.go similarity index 100% rename from pkg/util/math/rate.go rename to math/rate.go diff --git a/pkg/util/math/rate_test.go b/math/rate_test.go similarity index 100% rename from pkg/util/math/rate_test.go rename to math/rate_test.go