mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-11 17:47:20 +10:00
oom-killer: Free memory on pressure notification and use gradual interval backoff
This commit is contained in:
@@ -33,6 +33,7 @@ static void stopMemoryPressureMonitor() {
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
runtimeDebug "runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@@ -88,6 +89,7 @@ func (s *Service) Close() error {
|
|||||||
|
|
||||||
//export goMemoryPressureCallback
|
//export goMemoryPressureCallback
|
||||||
func goMemoryPressureCallback(status C.ulong) {
|
func goMemoryPressureCallback(status C.ulong) {
|
||||||
|
runtimeDebug.FreeOSMemory()
|
||||||
globalAccess.Lock()
|
globalAccess.Lock()
|
||||||
services := make([]*Service, len(globalServices))
|
services := make([]*Service, len(globalServices))
|
||||||
copy(services, globalServices)
|
copy(services, globalServices)
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ type adaptiveTimer struct {
|
|||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
timer *time.Timer
|
timer *time.Timer
|
||||||
state pressureState
|
state pressureState
|
||||||
|
currentInterval time.Duration
|
||||||
forceMinInterval bool
|
forceMinInterval bool
|
||||||
pendingPressureBaseline bool
|
pendingPressureBaseline bool
|
||||||
pressureBaseline memorySample
|
pressureBaseline memorySample
|
||||||
@@ -178,7 +179,9 @@ func (t *adaptiveTimer) poll() {
|
|||||||
t.state = t.nextState(sample)
|
t.state = t.nextState(sample)
|
||||||
if t.state == pressureStateNormal {
|
if t.state == pressureStateNormal {
|
||||||
t.forceMinInterval = false
|
t.forceMinInterval = false
|
||||||
t.pressureBaselineTime = time.Time{}
|
if !t.pressureBaselineTime.IsZero() && time.Since(t.pressureBaselineTime) > t.maxInterval {
|
||||||
|
t.pressureBaselineTime = time.Time{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.timer.Reset(t.intervalForState())
|
t.timer.Reset(t.intervalForState())
|
||||||
triggered = previousState != pressureStateTriggered && t.state == pressureStateTriggered
|
triggered = previousState != pressureStateTriggered && t.state == pressureStateTriggered
|
||||||
@@ -272,13 +275,19 @@ func (t *adaptiveTimer) availableThresholds(sample memorySample) pressureThresho
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *adaptiveTimer) intervalForState() time.Duration {
|
func (t *adaptiveTimer) intervalForState() time.Duration {
|
||||||
if t.state == pressureStateNormal {
|
switch {
|
||||||
return t.maxInterval
|
case t.forceMinInterval || t.state == pressureStateTriggered:
|
||||||
|
t.currentInterval = t.minInterval
|
||||||
|
case t.state == pressureStateArmed:
|
||||||
|
t.currentInterval = t.armedInterval
|
||||||
|
default:
|
||||||
|
if t.currentInterval == 0 {
|
||||||
|
t.currentInterval = t.maxInterval
|
||||||
|
} else {
|
||||||
|
t.currentInterval = min(t.currentInterval*2, t.maxInterval)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if t.forceMinInterval || t.state == pressureStateTriggered {
|
return t.currentInterval
|
||||||
return t.minInterval
|
|
||||||
}
|
|
||||||
return t.armedInterval
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *adaptiveTimer) logDetails(sample memorySample) string {
|
func (t *adaptiveTimer) logDetails(sample memorySample) string {
|
||||||
|
|||||||
Reference in New Issue
Block a user