diff --git a/src/init.cpp b/src/init.cpp index 7b6b188c257d..0f1f9e608493 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -508,7 +508,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) argsman.AddArg("-corepolicy", strprintf("Use Bitcoin Core policy defaults (default: %u)", DEFAULT_COREPOLICY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-datadir=", "Specify data directory", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS); argsman.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS); - argsman.AddArg("-dbcache=", strprintf("Maximum database cache size MiB (minimum %d, default: %d). Make sure you have enough RAM. In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", MIN_DB_CACHE >> 20, DEFAULT_DB_CACHE >> 20), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + argsman.AddArg("-dbcache=", strprintf("Maximum database cache size MiB (minimum %d, default: half of system RAM up to 16384 MiB, or %d MiB if detection fails). In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", MIN_DB_CACHE >> 20, DEFAULT_DB_CACHE >> 20), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-dbfilesize", strprintf("Target size of files within databases, in MiB (%u to %u, default: %u).", 1, 1024, diff --git a/src/node/caches.cpp b/src/node/caches.cpp index d5d69fc20443..d1ef6668c3a8 100644 --- a/src/node/caches.cpp +++ b/src/node/caches.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,13 @@ CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes) uint64_t db_cache_bytes = SaturatingLeftShift(*db_cache, 20); constexpr auto max_db_cache{sizeof(void*) == 4 ? MAX_32BIT_DBCACHE : std::numeric_limits::max()}; total_cache = std::max(MIN_DB_CACHE, std::min(db_cache_bytes, max_db_cache)); + } else { + uint64_t total_mem = GetTotalSystemMemory(); + if (total_mem > 0) { + constexpr uint64_t max_auto_cache{sizeof(void*) == 4 ? MAX_32BIT_DBCACHE : uint64_t{16} * 1024 * 1024 * 1024}; + uint64_t auto_cache = std::min(total_mem / 2, max_auto_cache); + total_cache = std::max(MIN_DB_CACHE, static_cast(auto_cache)); + } } IndexCacheSizes index_sizes; diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 5afd127ddd4e..de32d5911b94 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -28,6 +28,7 @@ #include // for ParseDustDynamicOpt #include #include +#include #include // for FormatMoney #include #include // For DEFAULT_SCRIPTCHECK_THREADS @@ -37,7 +38,9 @@ #include #endif +#include #include +#include #include #include #include @@ -694,7 +697,12 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con suffix.empty() ? getOption(option, "-prev") : DEFAULT_PRUNE_TARGET_MiB; case DatabaseCache: - return qlonglong(SettingToInt(setting(), DEFAULT_DB_CACHE >> 20)); + { + uint64_t total_mem = GetTotalSystemMemory(); + constexpr uint64_t max_auto_cache{sizeof(void*) == 4 ? uint64_t{1024} : uint64_t{16} * 1024}; + int default_mib = total_mem > 0 ? static_cast(std::min(total_mem / 2 >> 20, max_auto_cache)) : static_cast(DEFAULT_DB_CACHE >> 20); + return qlonglong(SettingToInt(setting(), default_mib)); + } case ThreadsScriptVerif: return qlonglong(SettingToInt(setting(), DEFAULT_SCRIPTCHECK_THREADS)); case Listen: diff --git a/src/util/mempressure.cpp b/src/util/mempressure.cpp index e2127fd798bc..0b3a48036ca4 100644 --- a/src/util/mempressure.cpp +++ b/src/util/mempressure.cpp @@ -12,6 +12,9 @@ #ifdef HAVE_LINUX_SYSINFO #include #endif +#ifdef __APPLE__ +#include +#endif #ifdef WIN32 #include #endif @@ -19,7 +22,7 @@ #include #include -size_t g_low_memory_threshold{0}; +size_t g_low_memory_threshold{256_MiB}; bool SystemNeedsMemoryReleased() { @@ -54,3 +57,28 @@ bool SystemNeedsMemoryReleased() // NOTE: sysconf(_SC_AVPHYS_PAGES) doesn't account for caches on at least Linux, so not safe to use here return false; } + +uint64_t GetTotalSystemMemory() +{ +#ifdef WIN32 + MEMORYSTATUSEX mem_status; + mem_status.dwLength = sizeof(mem_status); + if (GlobalMemoryStatusEx(&mem_status)) { + return mem_status.ullTotalPhys; + } +#endif +#ifdef HAVE_LINUX_SYSINFO + struct sysinfo sys_info; + if (!sysinfo(&sys_info)) { + return uint64_t(sys_info.totalram) * sys_info.mem_unit; + } +#endif +#ifdef __APPLE__ + int64_t memsize = 0; + size_t len = sizeof(memsize); + if (!sysctlbyname("hw.memsize", &memsize, &len, nullptr, 0) && memsize > 0) { + return static_cast(memsize); + } +#endif + return 0; +} diff --git a/src/util/mempressure.h b/src/util/mempressure.h index db2c5eb92119..b7104a9c66d7 100644 --- a/src/util/mempressure.h +++ b/src/util/mempressure.h @@ -6,9 +6,11 @@ #define BITCOIN_UTIL_MEMPRESSURE_H #include +#include extern size_t g_low_memory_threshold; bool SystemNeedsMemoryReleased(); +uint64_t GetTotalSystemMemory(); #endif // BITCOIN_UTIL_MEMPRESSURE_H