mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-09 03:18:09 -03:00
kernel: Move kernel-specific cache size options to kernel
Carrying non-kernel related fields in the cache sizes for the indexes is confusing for kernel library users. The cache sizes also are set currently with magic numbers in bitcoin-chainstate. The comments for the cache size calculations are also not completely clear. Solve these things by moving the kernel-specific cache size fields to their own struct. This slightly changes the way the cache is allocated if the txindex and/or blockfilterindex is used. Since they are now given precedence over the block tree db cache, this results in a bit less cache being allocated to the block tree db, coinsdb and coins caches. The effect is negligible though, i.e. cache sizes with default dbcache reported through the logs are: master: Cache configuration: * Using 2.0 MiB for block index database * Using 56.0 MiB for transaction index database * Using 49.0 MiB for basic block filter index database * Using 8.0 MiB for chain state database * Using 335.0 MiB for in-memory UTXO set (plus up to 286.1 MiB of unused mempool space) this branch: Cache configuration: * Using 2.0 MiB for block index database * Using 56.2 MiB for transaction index database * Using 49.2 MiB for basic block filter index database * Using 8.0 MiB for chain state database * Using 334.5 MiB for in-memory UTXO set (plus up to 286.1 MiB of unused mempool space) Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com>
This commit is contained in:
parent
19316eccaf
commit
41bc716488
9 changed files with 82 additions and 37 deletions
|
@ -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{MiBToBytes(nDefaultDbCache)};
|
||||
node::ChainstateLoadOptions options;
|
||||
auto [status, error] = node::LoadChainstate(chainman, cache_sizes, options);
|
||||
if (status != node::ChainstateLoadStatus::SUCCESS) {
|
||||
|
|
26
src/init.cpp
26
src/init.cpp
|
@ -32,6 +32,7 @@
|
|||
#include <interfaces/ipc.h>
|
||||
#include <interfaces/mining.h>
|
||||
#include <interfaces/node.h>
|
||||
#include <kernel/caches.h>
|
||||
#include <kernel/context.h>
|
||||
#include <key.h>
|
||||
#include <logging.h>
|
||||
|
@ -119,9 +120,10 @@ using common::AmountErrMsg;
|
|||
using common::InvalidPortErrMsg;
|
||||
using common::ResolveErrMsg;
|
||||
|
||||
using kernel::CacheSizes;
|
||||
|
||||
using node::ApplyArgsManOptions;
|
||||
using node::BlockManager;
|
||||
using node::CacheSizes;
|
||||
using node::CalculateCacheSizes;
|
||||
using node::ChainstateLoadResult;
|
||||
using node::ChainstateLoadStatus;
|
||||
|
@ -1603,18 +1605,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());
|
||||
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 +1629,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 +1648,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 +1674,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||
// ********************************************************* Step 8: start indexers
|
||||
|
||||
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
|
||||
g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), cache_sizes.tx_index, false, do_reindex);
|
||||
g_txindex = std::make_unique<TxIndex>(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));
|
||||
}
|
||||
|
||||
|
|
42
src/kernel/caches.h
Normal file
42
src/kernel/caches.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
// 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 <txdb.h>
|
||||
#include <util/check.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
//! Guard against truncation of values before converting.
|
||||
constexpr size_t MiBToBytes(int64_t mib)
|
||||
{
|
||||
Assert(std::countl_zero(static_cast<uint64_t>(mib)) >= 21); // Ensure sign bit is unset + enough zeros to shift.
|
||||
const int64_t bytes{mib << 20};
|
||||
Assert(static_cast<uint64_t>(bytes) <= std::numeric_limits<size_t>::max());
|
||||
return static_cast<size_t>(bytes);
|
||||
}
|
||||
|
||||
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, MiBToBytes(nMaxBlockDBCache));
|
||||
total_cache -= block_tree_db;
|
||||
coins_db = std::min(total_cache / 2, MiBToBytes(nMaxCoinsDBCache));
|
||||
total_cache -= coins_db;
|
||||
coins = total_cache; // the rest goes to the coins cache
|
||||
}
|
||||
};
|
||||
} // namespace kernel
|
||||
|
||||
#endif // BITCOIN_KERNEL_CACHES_H
|
|
@ -6,16 +6,18 @@
|
|||
|
||||
#include <common/args.h>
|
||||
#include <index/txindex.h>
|
||||
#include <kernel/caches.h>
|
||||
#include <txdb.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
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;
|
||||
|
@ -24,9 +26,6 @@ CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes)
|
|||
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<size_t>(nTotalCache)}};
|
||||
}
|
||||
} // namespace node
|
||||
|
|
|
@ -5,19 +5,22 @@
|
|||
#ifndef BITCOIN_NODE_CACHES_H
|
||||
#define BITCOIN_NODE_CACHES_H
|
||||
|
||||
#include <kernel/caches.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class ArgsManager;
|
||||
|
||||
namespace node {
|
||||
struct CacheSizes {
|
||||
int64_t block_tree_db;
|
||||
int64_t coins_db;
|
||||
int64_t coins;
|
||||
struct IndexCacheSizes {
|
||||
int64_t tx_index;
|
||||
int64_t filter_index;
|
||||
};
|
||||
struct CacheSizes {
|
||||
IndexCacheSizes index;
|
||||
kernel::CacheSizes kernel;
|
||||
};
|
||||
CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes = 0);
|
||||
} // namespace node
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
#include <chain.h>
|
||||
#include <coins.h>
|
||||
#include <consensus/params.h>
|
||||
#include <kernel/caches.h>
|
||||
#include <logging.h>
|
||||
#include <node/blockstorage.h>
|
||||
#include <node/caches.h>
|
||||
#include <sync.h>
|
||||
#include <threadsafety.h>
|
||||
#include <tinyformat.h>
|
||||
|
@ -29,6 +29,8 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using kernel::CacheSizes;
|
||||
|
||||
namespace node {
|
||||
// Complete initialization of chainstates after the initial call has been made
|
||||
// to ChainstateManager::InitializeChainstate().
|
||||
|
|
|
@ -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<ChainstateLoadStatus, bilingual_str>;
|
|||
*
|
||||
* 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
|
||||
|
|
|
@ -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<node::Warnings>();
|
||||
|
||||
m_cache_sizes = CalculateCacheSizes(m_args);
|
||||
|
||||
m_node.notifications = std::make_unique<KernelNotifications>(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<BlockTreeDB>(DBParams{
|
||||
.path = m_args.GetDataDirNet() / "blocks" / "index",
|
||||
.cache_bytes = static_cast<size_t>(m_cache_sizes.block_tree_db),
|
||||
.cache_bytes = static_cast<size_t>(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);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define BITCOIN_TEST_UTIL_SETUP_COMMON_H
|
||||
|
||||
#include <common/args.h> // IWYU pragma: export
|
||||
#include <kernel/caches.h>
|
||||
#include <kernel/context.h>
|
||||
#include <key.h>
|
||||
#include <node/caches.h>
|
||||
|
@ -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<void()> m_make_chainman{};
|
||||
|
|
Loading…
Reference in a new issue