diff --git a/src/init.cpp b/src/init.cpp index a151c9d0a9e..5a791851c7c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -487,7 +488,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) argsman.AddArg("-coinstatsindex", strprintf("Maintain coinstats index used by the gettxoutsetinfo RPC (default: %u)", DEFAULT_COINSTATSINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-conf=", strprintf("Specify path to read-only configuration file. Relative paths will be prefixed by datadir location (only useable from command line, not configuration file) (default: %s)", BITCOIN_CONF_FILENAME), 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("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: calculated from the `-dbcache` value or %u if not set)", node::GetDbBatchSize(DEFAULT_DB_CACHE)), 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("-includeconf=", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-allowignoredconf", strprintf("For backwards compatibility, treat an unused %s file in the datadir as a warning, not an error.", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); diff --git a/src/kernel/caches.h b/src/kernel/caches.h index 33ae604772b..1f2dab25dfb 100644 --- a/src/kernel/caches.h +++ b/src/kernel/caches.h @@ -16,6 +16,9 @@ static constexpr size_t MAX_BLOCK_DB_CACHE{2_MiB}; //! Max memory allocated to coin DB specific cache (bytes) static constexpr size_t MAX_COINS_DB_CACHE{8_MiB}; +//! The batch size of DEFAULT_KERNEL_CACHE +static constexpr size_t DEFAULT_DB_CACHE_BATCH{16_MiB}; + namespace kernel { struct CacheSizes { size_t block_tree_db; diff --git a/src/node/coins_view_args.cpp b/src/node/coins_view_args.cpp index 5d55143e832..2e513960dc7 100644 --- a/src/node/coins_view_args.cpp +++ b/src/node/coins_view_args.cpp @@ -2,6 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include + #include #include @@ -10,7 +12,9 @@ namespace node { void ReadCoinsViewArgs(const ArgsManager& args, CoinsViewOptions& options) { - if (auto value = args.GetIntArg("-dbbatchsize")) options.batch_write_bytes = *value; - if (auto value = args.GetIntArg("-dbcrashratio")) options.simulate_crash_ratio = *value; + if (const auto value = args.GetIntArg("-dbbatchsize")) options.batch_write_bytes = *value; + else options.batch_write_bytes = GetDbBatchSize(args.GetIntArg("-dbcache", DEFAULT_KERNEL_CACHE)); + + if (const auto value = args.GetIntArg("-dbcrashratio")) options.simulate_crash_ratio = *value; } } // namespace node diff --git a/src/node/coins_view_args.h b/src/node/coins_view_args.h index 71a7a671fd8..441f3bf4b79 100644 --- a/src/node/coins_view_args.h +++ b/src/node/coins_view_args.h @@ -5,10 +5,22 @@ #ifndef BITCOIN_NODE_COINS_VIEW_ARGS_H #define BITCOIN_NODE_COINS_VIEW_ARGS_H +#include + class ArgsManager; struct CoinsViewOptions; -namespace node { +namespace node +{ +static constexpr size_t GetDbBatchSize(const size_t dbcache_bytes) +{ + return std::clamp( + (dbcache_bytes / DEFAULT_KERNEL_CACHE) * DEFAULT_DB_CACHE_BATCH, + /*lo=*/DEFAULT_DB_CACHE_BATCH, + /*hi=*/256_MiB + ); +} + void ReadCoinsViewArgs(const ArgsManager& args, CoinsViewOptions& options); } // namespace node diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index c46144b34b4..20e41428f15 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -20,6 +20,7 @@ #include #include +#include using namespace util::hex_literals; @@ -1074,4 +1075,26 @@ BOOST_AUTO_TEST_CASE(coins_resource_is_used) PoolResourceTester::CheckAllDataAccountedFor(resource); } +BOOST_AUTO_TEST_CASE(db_batch_sizes) +{ + BOOST_REQUIRE_EQUAL(node::GetDbBatchSize(DEFAULT_KERNEL_CACHE), DEFAULT_DB_CACHE_BATCH); + BOOST_REQUIRE_EQUAL(node::GetDbBatchSize(0_MiB), DEFAULT_DB_CACHE_BATCH); + + BOOST_CHECK_EQUAL(node::GetDbBatchSize(4_MiB), 16'777'216); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(10_MiB), 16'777'216); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(45_MiB), 16'777'216); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(100_MiB), 16'777'216); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(450_MiB), 16'777'216); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(1000_MiB), 33'554'432); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(2000_MiB), 67'108'864); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(3000_MiB), 100'663'296); + +#if SIZE_MAX > UINT32_MAX + BOOST_CHECK_EQUAL(node::GetDbBatchSize(4500_MiB), 167'772'160); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(7000_MiB), 251'658'240); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(10000_MiB), 268'435'456); + BOOST_CHECK_EQUAL(node::GetDbBatchSize(45000_MiB), 268'435'456); +#endif +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/txdb.h b/src/txdb.h index 968b7c27810..589dc5dceca 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -21,16 +22,13 @@ class COutPoint; class uint256; -//! -dbbatchsize default (bytes) -static const int64_t nDefaultDbBatchSize = 16 << 20; - //! User-controlled performance and debug options. struct CoinsViewOptions { //! Maximum database write batch size in bytes. - size_t batch_write_bytes = nDefaultDbBatchSize; + size_t batch_write_bytes{DEFAULT_DB_CACHE_BATCH}; //! If non-zero, randomly exit when the database is flushed with (1/ratio) //! probability. - int simulate_crash_ratio = 0; + int simulate_crash_ratio{0}; }; /** CCoinsView backed by the coin database (chainstate/) */