* (global): added --no-mem-optimization flag
This commit adds a new command-line argument that disables memory optimizations AGH is using. These memory optimizations might be necessary on low-memory devices, but they aren't free and there's a performance hit (see #2044). Now they can be disabled - just pass --no-mem-optimization when you run AGH or when you install the service -- ./AdGuardHome -s install --no-mem-optimization Closes: #2044
This commit is contained in:
parent
cb8afde629
commit
b3a68bb806
|
@ -161,6 +161,9 @@ func run(args options) {
|
|||
// configure log level and output
|
||||
configureLogger(args)
|
||||
|
||||
// Go memory hacks
|
||||
memoryUsage(args)
|
||||
|
||||
// print the first message after logger is configured
|
||||
log.Println(version())
|
||||
log.Debug("Current working directory is %s", Context.workDir)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package home
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
)
|
||||
|
||||
// memoryUsage implements a couple of not really beautiful hacks which purpose is to
|
||||
// make OS reclaim the memory freed by AdGuard Home as soon as possible.
|
||||
// See this for the details on the performance hits & gains:
|
||||
// https://github.com/AdguardTeam/AdGuardHome/issues/2044#issuecomment-687042211
|
||||
func memoryUsage(args options) {
|
||||
if args.disableMemoryOptimization {
|
||||
log.Info("Memory optimization is disabled")
|
||||
return
|
||||
}
|
||||
|
||||
// Makes Go allocate heap at a slower pace
|
||||
// By default we keep it at 50%
|
||||
debug.SetGCPercent(50)
|
||||
|
||||
// madvdontneed: setting madvdontneed=1 will use MADV_DONTNEED
|
||||
// instead of MADV_FREE on Linux when returning memory to the
|
||||
// kernel. This is less efficient, but causes RSS numbers to drop
|
||||
// more quickly.
|
||||
_ = os.Setenv("GODEBUG", "madvdontneed=1")
|
||||
|
||||
// periodically call "debug.FreeOSMemory" so
|
||||
// that the OS could reclaim the free memory
|
||||
go func() {
|
||||
ticker := time.NewTicker(5 * time.Minute)
|
||||
for {
|
||||
select {
|
||||
case t := <-ticker.C:
|
||||
t.Second()
|
||||
log.Debug("Free OS memory")
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
|
@ -24,7 +24,11 @@ type options struct {
|
|||
// runningAsService flag is set to true when options are passed from the service runner
|
||||
runningAsService bool
|
||||
|
||||
glinetMode bool // Activate GL-Inet mode
|
||||
// disableMemoryOptimization - disables memory optimization hacks
|
||||
// see memoryUsage() function for the details
|
||||
disableMemoryOptimization bool
|
||||
|
||||
glinetMode bool // Activate GL-Inet compatibility mode
|
||||
}
|
||||
|
||||
// functions used for their side-effects
|
||||
|
@ -151,6 +155,13 @@ var noCheckUpdateArg = arg{
|
|||
func(o options) []string { return boolSliceOrNil(o.disableUpdate) },
|
||||
}
|
||||
|
||||
var disableMemoryOptimizationArg = arg{
|
||||
"Disable memory optimization",
|
||||
"no-mem-optimization", "",
|
||||
nil, func(o options) (options, error) { o.disableMemoryOptimization = true; return o, nil }, nil,
|
||||
func(o options) []string { return boolSliceOrNil(o.disableMemoryOptimization) },
|
||||
}
|
||||
|
||||
var verboseArg = arg{
|
||||
"Enable verbose output",
|
||||
"verbose", "v",
|
||||
|
@ -194,6 +205,7 @@ func init() {
|
|||
pidfileArg,
|
||||
checkConfigArg,
|
||||
noCheckUpdateArg,
|
||||
disableMemoryOptimizationArg,
|
||||
verboseArg,
|
||||
glinetArg,
|
||||
versionArg,
|
||||
|
|
31
main.go
31
main.go
|
@ -4,10 +4,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/home"
|
||||
)
|
||||
|
||||
|
@ -21,32 +17,5 @@ var channel = "release"
|
|||
var goarm = ""
|
||||
|
||||
func main() {
|
||||
memoryUsage()
|
||||
|
||||
home.Main(version, channel, goarm)
|
||||
}
|
||||
|
||||
// memoryUsage implements a couple of not really beautiful hacks which purpose is to
|
||||
// make OS reclaim the memory freed by AdGuard Home as soon as possible.
|
||||
func memoryUsage() {
|
||||
debug.SetGCPercent(10)
|
||||
|
||||
// madvdontneed: setting madvdontneed=1 will use MADV_DONTNEED
|
||||
// instead of MADV_FREE on Linux when returning memory to the
|
||||
// kernel. This is less efficient, but causes RSS numbers to drop
|
||||
// more quickly.
|
||||
_ = os.Setenv("GODEBUG", "madvdontneed=1")
|
||||
|
||||
// periodically call "debug.FreeOSMemory" so
|
||||
// that the OS could reclaim the free memory
|
||||
go func() {
|
||||
ticker := time.NewTicker(15 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case t := <-ticker.C:
|
||||
t.Second()
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue