node: smooth oversized `-dbcache` warnings
What changed, and why it matters
This commit changes the warning threshold that tells Bitcoin Core users when their database cache setting (-dbcache) is too large for their computer's RAM. Previously, the threshold jumped sharply at exactly 2 GiB of total RAM. The new formula removes that jump by reserving 2 GiB of RAM for non-cache use and applying the 75% rule only to the remaining memory. It is a user-experience and performance tuning change, not a security fix.
No security action required. Treat as a normal performance/usability improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change modifies ShouldWarnOversizedDbCache() in src/node/caches.h. The old logic used a piecewise threshold: DEFAULT_DB_CACHE below 2 GiB total RAM, otherwise 75% of total RAM. The new logic reserves DBCACHE_WARNING_RESERVED_RAM (2 GiB), takes 75% of the headroom above that reserve, and clamps the result to at least DEFAULT_DB_CACHE. Tests in src/test/caches_tests.cpp are updated to match the new continuous threshold curve. No cryptographic, network, or consensus code is touched.
Changed components
src/node/caches.hsrc/test/caches_tests.cppInspect captured patch +27 / −25
diff --git a/src/node/caches.h b/src/node/caches.h
index 4c66d39a..4fd14ed9 100644
--- a/src/node/caches.h
+++ b/src/node/caches.h
@@ -8,6 +8,7 @@
#include <kernel/caches.h>
#include <util/byte_units.h>
+#include <algorithm>
#include <cstddef>
#include <cstdint>
@@ -17,6 +18,8 @@ class ArgsManager;
static constexpr uint64_t MIN_DB_CACHE{4_MiB};
//! -dbcache default (bytes)
static constexpr uint64_t DEFAULT_DB_CACHE{DEFAULT_KERNEL_CACHE};
+//! Reserved non-dbcache memory usage.
+static constexpr uint64_t DBCACHE_WARNING_RESERVED_RAM{2_GiB};
namespace node {
uint64_t GetDefaultDBCache();
@@ -32,7 +35,8 @@ struct CacheSizes {
CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes = 0);
constexpr bool ShouldWarnOversizedDbCache(uint64_t dbcache, uint64_t total_ram) noexcept
{
- const uint64_t cap{(total_ram < 2_GiB) ? DEFAULT_DB_CACHE : (total_ram / 100) * 75};
+ const uint64_t available_ram{total_ram > DBCACHE_WARNING_RESERVED_RAM ? total_ram - DBCACHE_WARNING_RESERVED_RAM : 0};
+ const uint64_t cap{std::max<uint64_t>(DEFAULT_DB_CACHE, (available_ram / 4) * 3)};
return dbcache > cap;
}
diff --git a/src/test/caches_tests.cpp b/src/test/caches_tests.cpp
index 69c42f0b..c96bef7e 100644
--- a/src/test/caches_tests.cpp
+++ b/src/test/caches_tests.cpp
@@ -7,36 +7,34 @@
#include <boost/test/unit_test.hpp>
+#include <cstdint>
+
using namespace node;
+namespace {
+void CheckDbCacheWarnThreshold(uint64_t threshold, uint64_t total_ram)
+{
+ BOOST_CHECK(!ShouldWarnOversizedDbCache(threshold, total_ram));
+ BOOST_CHECK( ShouldWarnOversizedDbCache(threshold + 1, total_ram));
+}
+} // namespace
+
BOOST_AUTO_TEST_SUITE(caches_tests)
BOOST_AUTO_TEST_CASE(oversized_dbcache_warning)
{
- // memory restricted setup - cap is DEFAULT_DB_CACHE (450 MiB)
- BOOST_CHECK(!ShouldWarnOversizedDbCache(/*dbcache=*/4_MiB, /*total_ram=*/1_GiB)); // Under cap
- BOOST_CHECK( ShouldWarnOversizedDbCache(/*dbcache=*/512_MiB, /*total_ram=*/1_GiB)); // At cap
- BOOST_CHECK( ShouldWarnOversizedDbCache(/*dbcache=*/1500_MiB, /*total_ram=*/1_GiB)); // Over cap
-
- // 2 GiB RAM - cap is 75%
- BOOST_CHECK(!ShouldWarnOversizedDbCache(/*dbcache=*/1500_MiB, /*total_ram=*/2_GiB)); // Under cap
- BOOST_CHECK( ShouldWarnOversizedDbCache(/*dbcache=*/1600_MiB, /*total_ram=*/2_GiB)); // Over cap
-
- // 4 GiB RAM - cap is 75%
- BOOST_CHECK(!ShouldWarnOversizedDbCache(/*dbcache=*/2500_MiB, /*total_ram=*/4_GiB)); // Under cap
- BOOST_CHECK( ShouldWarnOversizedDbCache(/*dbcache=*/3500_MiB, /*total_ram=*/4_GiB)); // Over cap
-
- // 8 GiB RAM - cap is 75%
- BOOST_CHECK(!ShouldWarnOversizedDbCache(/*dbcache=*/6000_MiB, /*total_ram=*/8_GiB)); // Under cap
- BOOST_CHECK( ShouldWarnOversizedDbCache(/*dbcache=*/7000_MiB, /*total_ram=*/8_GiB)); // Over cap
-
- // 16 GiB RAM - cap is 75%
- BOOST_CHECK(!ShouldWarnOversizedDbCache(/*dbcache=*/10_GiB, /*total_ram=*/16_GiB)); // Under cap
- BOOST_CHECK( ShouldWarnOversizedDbCache(/*dbcache=*/15_GiB, /*total_ram=*/16_GiB)); // Over cap
-
- // 32 GiB RAM - cap is 75%
- BOOST_CHECK(!ShouldWarnOversizedDbCache(/*dbcache=*/20_GiB, /*total_ram=*/32_GiB)); // Under cap
- BOOST_CHECK( ShouldWarnOversizedDbCache(/*dbcache=*/30_GiB, /*total_ram=*/32_GiB)); // Over cap
+ BOOST_CHECK(!ShouldWarnOversizedDbCache(MIN_DB_CACHE, 1_GiB));
+
+ // Below DBCACHE_WARNING_RESERVED_RAM the existing fixed default dominates.
+ CheckDbCacheWarnThreshold(DEFAULT_DB_CACHE, 1_GiB);
+ CheckDbCacheWarnThreshold(DEFAULT_DB_CACHE, DBCACHE_WARNING_RESERVED_RAM);
+
+ // Above DBCACHE_WARNING_RESERVED_RAM the warning fires at 75% of the headroom.
+ CheckDbCacheWarnThreshold(((3_GiB - DBCACHE_WARNING_RESERVED_RAM) / 4) * 3, 3_GiB);
+
+ for (const auto total_ram : {8_GiB, 16_GiB, 32_GiB}) {
+ CheckDbCacheWarnThreshold(((total_ram - DBCACHE_WARNING_RESERVED_RAM) / 4) * 3, total_ram);
+ }
}
BOOST_AUTO_TEST_SUITE_END()
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.