2020-12-02 00:03:20 +00:00
|
|
|
package watchdog
|
|
|
|
|
2020-12-02 00:10:21 +00:00
|
|
|
// AdaptivePolicy is a policy that forces GC when the usage surpasses a
|
|
|
|
// user-configured percentage (Factor) of the available memory that remained
|
|
|
|
// after the last GC run.
|
2020-12-02 00:03:20 +00:00
|
|
|
//
|
|
|
|
// TODO tests
|
|
|
|
type AdaptivePolicy struct {
|
|
|
|
// Factor determines how much this policy will let the heap expand
|
|
|
|
// before it triggers.
|
|
|
|
//
|
|
|
|
// On every GC run, this policy recalculates the next target as
|
|
|
|
// (limit-currentHeap)*Factor (i.e. available*Factor).
|
|
|
|
//
|
|
|
|
// If the GC target calculated by the runtime is lower than the one
|
|
|
|
// calculated by this policy, this policy will set the new target, but the
|
|
|
|
// effect will be nil, since the the go runtime will run GC sooner than us
|
|
|
|
// anyway.
|
|
|
|
Factor float64
|
|
|
|
|
|
|
|
active bool
|
|
|
|
target uint64
|
|
|
|
initialized bool
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ Policy = (*AdaptivePolicy)(nil)
|
|
|
|
|
|
|
|
func (a *AdaptivePolicy) Evaluate(input PolicyInput) (trigger bool) {
|
|
|
|
if !a.initialized {
|
|
|
|
// when initializing, set the target to the limit; it will be reset
|
|
|
|
// when the first GC happens.
|
|
|
|
a.target = input.Limit
|
|
|
|
a.initialized = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// determine the value to compare utilisation against.
|
|
|
|
var actual uint64
|
|
|
|
switch input.Scope {
|
|
|
|
case ScopeSystem:
|
|
|
|
actual = input.SysStats.ActualUsed
|
|
|
|
case ScopeHeap:
|
|
|
|
actual = input.MemStats.HeapAlloc
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.GCTrigger {
|
|
|
|
available := float64(input.Limit) - float64(actual)
|
|
|
|
calc := uint64(available * a.Factor)
|
|
|
|
a.target = calc
|
|
|
|
}
|
|
|
|
if actual >= a.target {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|