121 lines
2.6 KiB
Go
Raw Normal View History

2024-03-07 16:16:07 +01:00
package protocolstate
2024-03-07 17:28:24 +01:00
import (
"context"
2024-03-11 19:48:56 +01:00
"sync"
"time"
"github.com/projectdiscovery/gologger"
2024-03-07 17:28:24 +01:00
"github.com/projectdiscovery/utils/env"
2024-03-11 19:48:56 +01:00
httputil "github.com/projectdiscovery/utils/http"
2024-03-07 17:28:24 +01:00
"github.com/projectdiscovery/utils/memguardian"
)
var (
2024-03-11 19:48:56 +01:00
MaxThreadsOnLowMemory = env.GetEnvOrDefault("MEMGUARDIAN_THREADS", 0)
MaxBytesBufferAllocOnLowMemory = env.GetEnvOrDefault("MEMGUARDIAN_ALLOC", 0)
memTimer *time.Ticker
cancelFunc context.CancelFunc
muGlobalChange sync.Mutex
2024-03-07 17:28:24 +01:00
)
2024-03-07 16:16:07 +01:00
func StartActiveMemGuardian(ctx context.Context) {
muGlobalChange.Lock()
defer muGlobalChange.Unlock()
if memguardian.DefaultMemGuardian == nil || memTimer != nil {
2024-03-11 19:48:56 +01:00
return
}
memTimer = time.NewTicker(memguardian.DefaultInterval)
ctx, cancelFunc = context.WithCancel(ctx)
ticker := memTimer
go func(t *time.Ticker) {
if t == nil {
return
}
for {
select {
case <-ctx.Done():
return
case <-t.C:
if IsLowOnMemory() {
_ = GlobalGuardBytesBufferAlloc()
} else {
GlobalRestoreBytesBufferAlloc()
}
2024-03-11 19:48:56 +01:00
}
}
}(ticker)
2024-03-11 19:48:56 +01:00
}
func StopActiveMemGuardian() {
muGlobalChange.Lock()
defer muGlobalChange.Unlock()
2024-03-11 19:48:56 +01:00
if memguardian.DefaultMemGuardian == nil {
return
}
if cancelFunc != nil {
cancelFunc()
cancelFunc = nil
}
if memTimer != nil {
memTimer.Stop()
memTimer = nil
}
2024-03-11 19:48:56 +01:00
}
2024-03-07 16:16:07 +01:00
func IsLowOnMemory() bool {
if memguardian.DefaultMemGuardian != nil && memguardian.DefaultMemGuardian.Warning.Load() {
return true
}
return false
}
2024-03-07 17:28:24 +01:00
2024-03-11 19:48:56 +01:00
// GuardThreads on caller
func GuardThreadsOrDefault(current int) int {
2024-03-07 17:28:24 +01:00
if MaxThreadsOnLowMemory > 0 {
return MaxThreadsOnLowMemory
}
fraction := int(current / 5)
if fraction > 0 {
return fraction
}
return 1
}
2024-03-11 19:48:56 +01:00
// Global setting
func GlobalGuardBytesBufferAlloc() error {
if !muGlobalChange.TryLock() {
2024-03-11 19:48:56 +01:00
return nil
}
defer muGlobalChange.Unlock()
// if current capacity was not reduced decrease it
if MaxBytesBufferAllocOnLowMemory > 0 && httputil.DefaultBytesBufferAlloc == httputil.GetPoolSize() {
gologger.Debug().Msgf("reducing bytes.buffer pool size to: %d", MaxBytesBufferAllocOnLowMemory)
delta := httputil.GetPoolSize() - int64(MaxBytesBufferAllocOnLowMemory)
return httputil.ChangePoolSize(-delta)
}
return nil
}
// Global setting
func GlobalRestoreBytesBufferAlloc() {
if !muGlobalChange.TryLock() {
2024-03-11 19:48:56 +01:00
return
}
defer muGlobalChange.Unlock()
if httputil.DefaultBytesBufferAlloc != httputil.GetPoolSize() {
delta := httputil.DefaultBytesBufferAlloc - httputil.GetPoolSize()
gologger.Debug().Msgf("restoring bytes.buffer pool size to: %d", httputil.DefaultBytesBufferAlloc)
2024-03-11 19:54:23 +01:00
_ = httputil.ChangePoolSize(delta)
2024-03-11 19:48:56 +01:00
}
}