From a70b8692d9fbc9ec32f6a5058939a090a84dfdea Mon Sep 17 00:00:00 2001 From: georgehao Date: Tue, 1 Apr 2025 22:09:26 +0800 Subject: [PATCH] address comments --- cmd/utils/flags.go | 27 +++++++++++++++++++++++++-- internal/debug/api.go | 3 +++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 48781851a2..2c8c37c6e3 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -24,11 +24,13 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" "net" "net/http" "os" "path/filepath" + godebug "runtime/debug" "strconv" "strings" "time" @@ -74,6 +76,7 @@ import ( "github.com/ethereum/go-ethereum/triedb/hashdb" "github.com/ethereum/go-ethereum/triedb/pathdb" pcsclite "github.com/gballet/go-libpcsclite" + gopsutil "github.com/shirou/gopsutil/mem" "github.com/urfave/cli/v2" ) @@ -1575,18 +1578,38 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { setRequiredBlocks(ctx, cfg) setLes(ctx, cfg) + // Cap the cache allowance and tune the garbage collector + mem, err := gopsutil.VirtualMemory() + if err == nil { + if 32<<(^uintptr(0)>>63) == 32 && mem.Total > 2*1024*1024*1024 { + log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024) + mem.Total = 2 * 1024 * 1024 * 1024 + } + allowance := int(mem.Total / 1024 / 1024 / 3) + if cache := ctx.Int(CacheFlag.Name); cache > allowance { + log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) + ctx.Set(CacheFlag.Name, strconv.Itoa(allowance)) + } + } + // Ensure Go's GC ignores the database cache for trigger percentage + cache := ctx.Int(CacheFlag.Name) + gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024))) + + log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc)) + godebug.SetGCPercent(int(gogc)) + if ctx.IsSet(SyncTargetFlag.Name) { cfg.SyncMode = ethconfig.FullSync // dev sync target forces full sync } else if ctx.IsSet(SyncModeFlag.Name) { value := ctx.String(SyncModeFlag.Name) - if err := cfg.SyncMode.UnmarshalText([]byte(value)); err != nil { + if err = cfg.SyncMode.UnmarshalText([]byte(value)); err != nil { Fatalf("--%v: %v", SyncModeFlag.Name, err) } } if ctx.IsSet(ChainHistoryFlag.Name) { value := ctx.String(ChainHistoryFlag.Name) - if err := cfg.HistoryMode.UnmarshalText([]byte(value)); err != nil { + if err = cfg.HistoryMode.UnmarshalText([]byte(value)); err != nil { Fatalf("--%s: %v", ChainHistoryFlag.Name, err) } } diff --git a/internal/debug/api.go b/internal/debug/api.go index 0287d4bf65..c3a1e5e059 100644 --- a/internal/debug/api.go +++ b/internal/debug/api.go @@ -238,6 +238,9 @@ func (*HandlerT) SetGCPercent(v int) int { } // SetMemoryLimit sets the GOMEMLIMIT for the process. It returns the previous limit. +// Note: +// - Geth also allocates memory off-heap, particularly for fastCache and Pebble, which can be non-trivial (a few gigabytes by default). +// - Setting the limit too low will cause Geth to become unresponsive. func (*HandlerT) SetMemoryLimit(limit int64) int64 { return debug.SetMemoryLimit(limit) }