diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index bab09f13d9b..3b551e5c178 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -123,10 +123,7 @@ int main(int argc, char* argv[]) util::SignalInterrupt interrupt; ChainstateManager chainman{interrupt, chainman_opts, blockman_opts}; - node::CacheSizes cache_sizes; - cache_sizes.block_tree_db = 2 << 20; - cache_sizes.coins_db = 2 << 22; - cache_sizes.coins = (450 << 20) - (2 << 20) - (2 << 22); + kernel::CacheSizes cache_sizes{nDefaultDbCache << 20}; node::ChainstateLoadOptions options; auto [status, error] = node::LoadChainstate(chainman, cache_sizes, options); if (status != node::ChainstateLoadStatus::SUCCESS) { diff --git a/src/init.cpp b/src/init.cpp index a4ad2771cc7..878e11518b0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -121,7 +122,6 @@ using common::ResolveErrMsg; using node::ApplyArgsManOptions; using node::BlockManager; -using node::CacheSizes; using node::CalculateCacheSizes; using node::ChainstateLoadResult; using node::ChainstateLoadStatus; @@ -1177,7 +1177,7 @@ static ChainstateLoadResult InitAndLoadChainstate( NodeContext& node, bool do_reindex, const bool do_reindex_chainstate, - CacheSizes& cache_sizes, + const kernel::CacheSizes& cache_sizes, const ArgsManager& args) { const CChainParams& chainparams = Params(); @@ -1603,18 +1603,18 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) ReadNotificationArgs(args, kernel_notifications); // cache size calculations - CacheSizes cache_sizes = CalculateCacheSizes(args, g_enabled_filter_types.size()); + const auto [index_cache_sizes, kernel_cache_sizes] = CalculateCacheSizes(args, g_enabled_filter_types.size()); - LogPrintf("Cache configuration:\n"); - LogPrintf("* Using %.1f MiB for block index database\n", cache_sizes.block_tree_db * (1.0 / 1024 / 1024)); + LogInfo("Cache configuration:"); + LogInfo("* Using %.1f MiB for block index database", kernel_cache_sizes.block_tree_db * (1.0 / 1024 / 1024)); if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { - LogPrintf("* Using %.1f MiB for transaction index database\n", cache_sizes.tx_index * (1.0 / 1024 / 1024)); + LogInfo("* Using %.1f MiB for transaction index database", index_cache_sizes.tx_index * (1.0 / 1024 / 1024)); } for (BlockFilterType filter_type : g_enabled_filter_types) { - LogPrintf("* Using %.1f MiB for %s block filter index database\n", - cache_sizes.filter_index * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type)); + LogInfo("* Using %.1f MiB for %s block filter index database", + index_cache_sizes.filter_index * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type)); } - LogPrintf("* Using %.1f MiB for chain state database\n", cache_sizes.coins_db * (1.0 / 1024 / 1024)); + LogInfo("* Using %.1f MiB for chain state database", kernel_cache_sizes.coins_db * (1.0 / 1024 / 1024)); assert(!node.mempool); assert(!node.chainman); @@ -1627,7 +1627,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node, do_reindex, do_reindex_chainstate, - cache_sizes, + kernel_cache_sizes, args); if (status == ChainstateLoadStatus::FAILURE && !do_reindex && !ShutdownRequested(node)) { // suggest a reindex @@ -1646,7 +1646,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node, do_reindex, do_reindex_chainstate, - cache_sizes, + kernel_cache_sizes, args); } if (status != ChainstateLoadStatus::SUCCESS && status != ChainstateLoadStatus::INTERRUPTED) { @@ -1672,12 +1672,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // ********************************************************* Step 8: start indexers if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { - g_txindex = std::make_unique(interfaces::MakeChain(node), cache_sizes.tx_index, false, do_reindex); + g_txindex = std::make_unique(interfaces::MakeChain(node), index_cache_sizes.tx_index, false, do_reindex); node.indexes.emplace_back(g_txindex.get()); } for (const auto& filter_type : g_enabled_filter_types) { - InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, cache_sizes.filter_index, false, do_reindex); + InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, index_cache_sizes.filter_index, false, do_reindex); node.indexes.emplace_back(GetBlockFilterIndex(filter_type)); } diff --git a/src/kernel/caches.h b/src/kernel/caches.h new file mode 100644 index 00000000000..2eab84df6be --- /dev/null +++ b/src/kernel/caches.h @@ -0,0 +1,34 @@ +// Copyright (c) 2024-present The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_KERNEL_CACHES_H +#define BITCOIN_KERNEL_CACHES_H + +#include + +#include + +//! Max memory allocated to block tree DB specific cache (bytes) +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}; + +namespace kernel { +struct CacheSizes { + size_t block_tree_db; + size_t coins_db; + size_t coins; + + CacheSizes(size_t total_cache) + { + block_tree_db = std::min(total_cache / 8, MAX_BLOCK_DB_CACHE); + total_cache -= block_tree_db; + coins_db = std::min(total_cache / 2, MAX_COINS_DB_CACHE); + total_cache -= coins_db; + coins = total_cache; // the rest goes to the coins cache + } +}; +} // namespace kernel + +#endif // BITCOIN_KERNEL_CACHES_H diff --git a/src/node/caches.cpp b/src/node/caches.cpp index 01b08e320d7..50b8bceebe8 100644 --- a/src/node/caches.cpp +++ b/src/node/caches.cpp @@ -6,27 +6,25 @@ #include #include +#include #include +#include +#include + namespace node { CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes) { int64_t nTotalCache = (args.GetIntArg("-dbcache", nDefaultDbCache) << 20); nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache - CacheSizes sizes; - sizes.block_tree_db = std::min(nTotalCache / 8, nMaxBlockDBCache << 20); - nTotalCache -= sizes.block_tree_db; + IndexCacheSizes sizes; sizes.tx_index = std::min(nTotalCache / 8, args.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxTxIndexCache << 20 : 0); nTotalCache -= sizes.tx_index; - sizes.filter_index = 0; if (n_indexes > 0) { int64_t max_cache = std::min(nTotalCache / 8, max_filter_index_cache << 20); sizes.filter_index = max_cache / n_indexes; nTotalCache -= sizes.filter_index * n_indexes; } - sizes.coins_db = std::min(nTotalCache / 2, nMaxCoinsDBCache << 20); - nTotalCache -= sizes.coins_db; - sizes.coins = nTotalCache; // the rest goes to in-memory cache - return sizes; + return {sizes, kernel::CacheSizes{static_cast(nTotalCache)}}; } } // namespace node diff --git a/src/node/caches.h b/src/node/caches.h index 67388b91fd2..1818dff1f82 100644 --- a/src/node/caches.h +++ b/src/node/caches.h @@ -5,18 +5,21 @@ #ifndef BITCOIN_NODE_CACHES_H #define BITCOIN_NODE_CACHES_H +#include + #include #include class ArgsManager; namespace node { +struct IndexCacheSizes { + int64_t tx_index{0}; + int64_t filter_index{0}; +}; struct CacheSizes { - int64_t block_tree_db; - int64_t coins_db; - int64_t coins; - int64_t tx_index; - int64_t filter_index; + IndexCacheSizes index; + kernel::CacheSizes kernel; }; CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes = 0); } // namespace node diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index e56896fb224..660d2c3289c 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -8,9 +8,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -29,6 +29,8 @@ #include #include +using kernel::CacheSizes; + namespace node { // Complete initialization of chainstates after the initial call has been made // to ChainstateManager::InitializeChainstate(). diff --git a/src/node/chainstate.h b/src/node/chainstate.h index bb0c4f2b87e..ce414fa0434 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -14,9 +14,11 @@ class CTxMemPool; -namespace node { - +namespace kernel { struct CacheSizes; +} // namespace kernel + +namespace node { struct ChainstateLoadOptions { CTxMemPool* mempool{nullptr}; @@ -69,7 +71,7 @@ using ChainstateLoadResult = std::tuple; * * LoadChainstate returns a (status code, error string) tuple. */ -ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes, +ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const kernel::CacheSizes& cache_sizes, const ChainstateLoadOptions& options); ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options); } // namespace node diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 12feba09a54..5ede59b82a1 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -66,7 +66,6 @@ using kernel::BlockTreeDB; using node::ApplyArgsManOptions; using node::BlockAssembler; using node::BlockManager; -using node::CalculateCacheSizes; using node::KernelNotifications; using node::LoadChainstate; using node::RegenerateCommitments; @@ -228,8 +227,6 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) Assert(error.empty()); m_node.warnings = std::make_unique(); - m_cache_sizes = CalculateCacheSizes(m_args); - m_node.notifications = std::make_unique(Assert(m_node.shutdown_request), m_node.exit_status, *Assert(m_node.warnings)); m_make_chainman = [this, &chainparams, opts] { @@ -255,7 +252,7 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) LOCK(m_node.chainman->GetMutex()); m_node.chainman->m_blockman.m_block_tree_db = std::make_unique(DBParams{ .path = m_args.GetDataDirNet() / "blocks" / "index", - .cache_bytes = static_cast(m_cache_sizes.block_tree_db), + .cache_bytes = static_cast(m_kernel_cache_sizes.block_tree_db), .memory_only = true, }); }; @@ -291,7 +288,7 @@ void ChainTestingSetup::LoadVerifyActivateChainstate() options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS); options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL); options.require_full_verification = m_args.IsArgSet("-checkblocks") || m_args.IsArgSet("-checklevel"); - auto [status, error] = LoadChainstate(chainman, m_cache_sizes, options); + auto [status, error] = LoadChainstate(chainman, m_kernel_cache_sizes, options); assert(status == node::ChainstateLoadStatus::SUCCESS); std::tie(status, error) = VerifyLoadedChainstate(chainman, options); diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index b0f7bdade20..33ad2584573 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -6,6 +6,7 @@ #define BITCOIN_TEST_UTIL_SETUP_COMMON_H #include // IWYU pragma: export +#include #include #include #include @@ -103,7 +104,7 @@ struct BasicTestingSetup { * initialization behaviour. */ struct ChainTestingSetup : public BasicTestingSetup { - node::CacheSizes m_cache_sizes{}; + kernel::CacheSizes m_kernel_cache_sizes{node::CalculateCacheSizes(m_args).kernel}; bool m_coins_db_in_memory{true}; bool m_block_tree_db_in_memory{true}; std::function m_make_chainman{}; diff --git a/src/txdb.h b/src/txdb.h index 671cbd12866..57ae5267135 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -27,16 +27,12 @@ static const int64_t nDefaultDbCache = 450; static const int64_t nDefaultDbBatchSize = 16 << 20; //! min. -dbcache (MiB) static const int64_t nMinDbCache = 4; -//! Max memory allocated to block tree DB specific cache (MiB) -static const int64_t nMaxBlockDBCache = 2; // Unlike for the UTXO database, for the txindex scenario the leveldb cache make // a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991 //! Max memory allocated to tx index DB specific cache in MiB. static const int64_t nMaxTxIndexCache = 1024; //! Max memory allocated to all block filter index caches combined in MiB. static const int64_t max_filter_index_cache = 1024; -//! Max memory allocated to coin DB specific cache (MiB) -static const int64_t nMaxCoinsDBCache = 8; //! User-controlled performance and debug options. struct CoinsViewOptions {