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