oom-killer: Free memory on pressure notification and use gradual interval backoff

This commit is contained in:
世界
2026-04-07 21:19:40 +08:00
parent 51166f4601
commit ac9c0e7a81
2 changed files with 18 additions and 7 deletions

View File

@@ -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)

View File

@@ -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 {