diff --git a/cmd/XDC/main.go b/cmd/XDC/main.go index 3a028fe180aa..4581e1a19201 100644 --- a/cmd/XDC/main.go +++ b/cmd/XDC/main.go @@ -93,6 +93,7 @@ var ( //utils.CacheDatabaseFlag, //utils.CacheGCFlag, //utils.TrieCacheGenFlag, + utils.FDLimitFlag, utils.ListenPortFlag, utils.MaxPeersFlag, utils.MaxPendingPeersFlag, diff --git a/cmd/XDC/usage.go b/cmd/XDC/usage.go index f0e567bd555f..c88928a53426 100644 --- a/cmd/XDC/usage.go +++ b/cmd/XDC/usage.go @@ -123,15 +123,16 @@ var AppHelpFlagGroups = []flagGroup{ // utils.TxPoolLifetimeFlag, // }, //}, - //{ - // Name: "PERFORMANCE TUNING", - // Flags: []cli.Flag{ - // utils.CacheFlag, - // utils.CacheDatabaseFlag, - // utils.CacheGCFlag, - // utils.TrieCacheGenFlag, - // }, - //}, + { + Name: "PERFORMANCE TUNING", + Flags: []cli.Flag{ + // utils.CacheFlag, + // utils.CacheDatabaseFlag, + // utils.CacheGCFlag, + // utils.TrieCacheGenFlag, + utils.FDLimitFlag, + }, + }, { Name: "ACCOUNT", Flags: []cli.Flag{ diff --git a/cmd/gc/main.go b/cmd/gc/main.go index 6d3b2bdf546e..b017b90bedc5 100644 --- a/cmd/gc/main.go +++ b/cmd/gc/main.go @@ -52,7 +52,7 @@ type ResultProcessNode struct { func main() { flag.Parse() - db, _ := leveldb.New(*dir, ethconfig.Defaults.DatabaseCache, utils.MakeDatabaseHandles(), "") + db, _ := leveldb.New(*dir, ethconfig.Defaults.DatabaseCache, utils.MakeDatabaseHandles(0), "") lddb := rawdb.NewDatabase(db) head := core.GetHeadBlockHash(lddb) currentHeader := core.GetHeader(lddb, head, core.GetBlockNumber(lddb, head)) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 18f5131278c0..c178bee59fe3 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -313,6 +313,10 @@ var ( Usage: "Percentage of cache memory allowance to use for trie pruning", Value: 25, } + FDLimitFlag = cli.IntFlag{ + Name: "fdlimit", + Usage: "Raise the open file descriptor resource limit (default = system fd limit)", + } // Miner settings StakingEnabledFlag = cli.BoolFlag{ Name: "mine", @@ -817,11 +821,24 @@ func setPrefix(ctx *cli.Context, cfg *node.Config) { // MakeDatabaseHandles raises out the number of allowed file handles per process // for XDC and returns half of the allowance to assign to the database. -func MakeDatabaseHandles() int { +func MakeDatabaseHandles(max int) int { limit, err := fdlimit.Maximum() if err != nil { Fatalf("Failed to retrieve file descriptor allowance: %v", err) } + switch { + case max == 0: + // User didn't specify a meaningful value, use system limits + case max < 128: + // User specified something unhealthy, just use system defaults + log.Error("File descriptor limit invalid (<128)", "had", max, "updated", limit) + case max > limit: + // User requested more than the OS allows, notify that we can't allocate it + log.Warn("Requested file descriptors denied by OS", "req", max, "limit", limit) + default: + // User limit is meaningful and within allowed range, use that + limit = max + } raised, err := fdlimit.Raise(uint64(limit)) if err != nil { Fatalf("Failed to raise file descriptor allowance: %v", err) @@ -1179,7 +1196,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 } - cfg.DatabaseHandles = MakeDatabaseHandles() + cfg.DatabaseHandles = MakeDatabaseHandles(ctx.GlobalInt(FDLimitFlag.Name)) if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) @@ -1268,7 +1285,7 @@ func SetupNetwork(ctx *cli.Context) { func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { var ( cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 - handles = MakeDatabaseHandles() + handles = MakeDatabaseHandles(ctx.GlobalInt(FDLimitFlag.Name)) ) name := "chaindata" if ctx.GlobalBool(LightModeFlag.Name) {