mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 11:28:59 +00:00
65aaa607ab
Change made by: - running "gvt fetch" on each of the packages mentioned in Godeps/Godeps.json - `rm -rf Godeps` - tweaking the build scripts to not mention Godeps - tweaking the build scripts to test `./lib/...`, `./cmd/...` explicitly (to avoid testing vendor) - tweaking the build scripts to not juggle GOPATH for Godeps and instead set GO15VENDOREXPERIMENT. This also results in some updated packages at the same time I bet. Building with Go 1.3 and 1.4 still *works* but won't use our vendored dependencies - the user needs to have the actual packages in their GOPATH then, which they'll get with a normal "go get". Building with Go 1.6+ will get our vendored dependencies by default even when not using our build script, which is nice. By doing this we gain some freedom in that we can pick and choose manually what to include in vendor, as it's not based on just dependency analysis of our own code. This is also a risk as we might pick up dependencies we are unaware of, as the build may work locally with those packages present in GOPATH. On the other hand the build server will detect this as it has no packages in it's GOPATH beyond what is included in the repo. Recommended tool to manage dependencies is github.com/FiloSottile/gvt.
119 lines
2.8 KiB
Go
119 lines
2.8 KiB
Go
package metrics
|
|
|
|
import (
|
|
"math"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// EWMAs continuously calculate an exponentially-weighted moving average
|
|
// based on an outside source of clock ticks.
|
|
type EWMA interface {
|
|
Rate() float64
|
|
Snapshot() EWMA
|
|
Tick()
|
|
Update(int64)
|
|
}
|
|
|
|
// NewEWMA constructs a new EWMA with the given alpha.
|
|
func NewEWMA(alpha float64) EWMA {
|
|
if UseNilMetrics {
|
|
return NilEWMA{}
|
|
}
|
|
return &StandardEWMA{alpha: alpha}
|
|
}
|
|
|
|
// NewEWMA1 constructs a new EWMA for a one-minute moving average.
|
|
func NewEWMA1() EWMA {
|
|
return NewEWMA(1 - math.Exp(-5.0/60.0/1))
|
|
}
|
|
|
|
// NewEWMA5 constructs a new EWMA for a five-minute moving average.
|
|
func NewEWMA5() EWMA {
|
|
return NewEWMA(1 - math.Exp(-5.0/60.0/5))
|
|
}
|
|
|
|
// NewEWMA15 constructs a new EWMA for a fifteen-minute moving average.
|
|
func NewEWMA15() EWMA {
|
|
return NewEWMA(1 - math.Exp(-5.0/60.0/15))
|
|
}
|
|
|
|
// EWMASnapshot is a read-only copy of another EWMA.
|
|
type EWMASnapshot float64
|
|
|
|
// Rate returns the rate of events per second at the time the snapshot was
|
|
// taken.
|
|
func (a EWMASnapshot) Rate() float64 { return float64(a) }
|
|
|
|
// Snapshot returns the snapshot.
|
|
func (a EWMASnapshot) Snapshot() EWMA { return a }
|
|
|
|
// Tick panics.
|
|
func (EWMASnapshot) Tick() {
|
|
panic("Tick called on an EWMASnapshot")
|
|
}
|
|
|
|
// Update panics.
|
|
func (EWMASnapshot) Update(int64) {
|
|
panic("Update called on an EWMASnapshot")
|
|
}
|
|
|
|
// NilEWMA is a no-op EWMA.
|
|
type NilEWMA struct{}
|
|
|
|
// Rate is a no-op.
|
|
func (NilEWMA) Rate() float64 { return 0.0 }
|
|
|
|
// Snapshot is a no-op.
|
|
func (NilEWMA) Snapshot() EWMA { return NilEWMA{} }
|
|
|
|
// Tick is a no-op.
|
|
func (NilEWMA) Tick() {}
|
|
|
|
// Update is a no-op.
|
|
func (NilEWMA) Update(n int64) {}
|
|
|
|
// StandardEWMA is the standard implementation of an EWMA and tracks the number
|
|
// of uncounted events and processes them on each tick. It uses the
|
|
// sync/atomic package to manage uncounted events.
|
|
type StandardEWMA struct {
|
|
uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment
|
|
alpha float64
|
|
rate float64
|
|
init bool
|
|
mutex sync.Mutex
|
|
}
|
|
|
|
// Rate returns the moving average rate of events per second.
|
|
func (a *StandardEWMA) Rate() float64 {
|
|
a.mutex.Lock()
|
|
defer a.mutex.Unlock()
|
|
return a.rate * float64(1e9)
|
|
}
|
|
|
|
// Snapshot returns a read-only copy of the EWMA.
|
|
func (a *StandardEWMA) Snapshot() EWMA {
|
|
return EWMASnapshot(a.Rate())
|
|
}
|
|
|
|
// Tick ticks the clock to update the moving average. It assumes it is called
|
|
// every five seconds.
|
|
func (a *StandardEWMA) Tick() {
|
|
count := atomic.LoadInt64(&a.uncounted)
|
|
atomic.AddInt64(&a.uncounted, -count)
|
|
instantRate := float64(count) / float64(5e9)
|
|
a.mutex.Lock()
|
|
defer a.mutex.Unlock()
|
|
if a.init {
|
|
a.rate += a.alpha * (instantRate - a.rate)
|
|
} else {
|
|
a.init = true
|
|
a.rate = instantRate
|
|
}
|
|
}
|
|
|
|
// Update adds n uncounted events.
|
|
func (a *StandardEWMA) Update(n int64) {
|
|
atomic.AddInt64(&a.uncounted, n)
|
|
}
|