Skip to content

Commit

Permalink
init: Use size_t consistently for cache sizes
Browse files Browse the repository at this point in the history
This avoids having to rely on implicit casts when passing them to the
various functions allocating the caches.

This also ensures that if the requested amount of db_cache does not fit
in a size_t, it is clamped to the maximum value of a size_t.

Also take this opportunity to make the total amounts of cache in the
chainstate manager a size_t too.
  • Loading branch information
TheCharlatan committed Jan 11, 2025
1 parent 91da0cf commit 45fe603
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/bitcoin-chainstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ int main(int argc, char* argv[])
util::SignalInterrupt interrupt;
ChainstateManager chainman{interrupt, chainman_opts, blockman_opts};

kernel::CacheSizes cache_sizes{DEFAULT_KERNEL_CACHE << 20};
kernel::CacheSizes cache_sizes{DEFAULT_KERNEL_CACHE};
node::ChainstateLoadOptions options;
auto [status, error] = node::LoadChainstate(chainman, cache_sizes, options);
if (status != node::ChainstateLoadStatus::SUCCESS) {
Expand Down
6 changes: 3 additions & 3 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
argsman.AddArg("-conf=<file>", 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=<dir>", "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=<n>", strprintf("Maximum database cache size <n> 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, DEFAULT_DB_CACHE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> 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=<file>", "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);
argsman.AddArg("-loadblock=<file>", "Imports blocks from external file on startup", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
Expand Down Expand Up @@ -1179,7 +1179,7 @@ static ChainstateLoadResult InitAndLoadChainstate(
NodeContext& node,
bool do_reindex,
const bool do_reindex_chainstate,
CacheSizes& cache_sizes,
const CacheSizes& cache_sizes,
const ArgsManager& args)
{
const CChainParams& chainparams = Params();
Expand Down Expand Up @@ -1605,7 +1605,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
ReadNotificationArgs(args, kernel_notifications);

// cache size calculations
auto [index_cache_sizes, kernel_cache_sizes] = CalculateCacheSizes(args, g_enabled_filter_types.size());
const auto [index_cache_sizes, kernel_cache_sizes] = CalculateCacheSizes(args, g_enabled_filter_types.size());

LogInfo("Cache configuration:");
LogInfo("* Using %.1f MiB for block index database", kernel_cache_sizes.block_tree_db * (1.0 / 1024 / 1024));
Expand Down
4 changes: 2 additions & 2 deletions src/kernel/caches.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

#include <algorithm>

//! Suggested default amount of cache reserved for the kernel (MiB)
static constexpr int64_t DEFAULT_KERNEL_CACHE{450};
//! Suggested default amount of cache reserved for the kernel (bytes)
static constexpr size_t DEFAULT_KERNEL_CACHE{450_MiB};
//! 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)
Expand Down
35 changes: 21 additions & 14 deletions src/node/caches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,38 @@
#include <common/args.h>
#include <index/txindex.h>
#include <kernel/caches.h>
#include <logging.h>
#include <util/byte_units.h>

#include <algorithm>
#include <optional>
#include <string>

// 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 constexpr int64_t MAX_TX_INDEX_CACHE{1024};
//! Max memory allocated to all block filter index caches combined in MiB.
static constexpr int64_t MAX_FILTER_INDEX_CACHE{1024};
//! Max memory allocated to tx index DB specific cache in bytes.
static constexpr size_t MAX_TX_INDEX_CACHE{1024_MiB};
//! Max memory allocated to all block filter index caches combined in bytes.
static constexpr size_t MAX_FILTER_INDEX_CACHE{1024_MiB};

namespace node {
CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes)
{
int64_t nTotalCache = (args.GetIntArg("-dbcache", DEFAULT_DB_CACHE) << 20);
nTotalCache = std::max(nTotalCache, MIN_DB_CACHE << 20);
IndexCacheSizes sizes;
sizes.tx_index = std::min(nTotalCache / 8, args.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? MAX_TX_INDEX_CACHE << 20 : 0);
nTotalCache -= sizes.tx_index;
sizes.filter_index = 0;
// Convert -dbcache from MiB units to bytes. The total chache is floored by MIN_DB_CACHE and capped by max size_t value.
size_t total_cache{DEFAULT_DB_CACHE};
if (auto db_cache = args.GetIntArg("-dbcache")) {
total_cache = std::max(MIN_DB_CACHE, SaturatingLeftShift<size_t>(*db_cache, 20));
}

IndexCacheSizes index_sizes;
index_sizes.tx_index = std::min(total_cache / 8, args.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? MAX_TX_INDEX_CACHE : 0);
total_cache -= index_sizes.tx_index;
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;
int64_t max_cache = std::min(total_cache / 8, MAX_FILTER_INDEX_CACHE);
index_sizes.filter_index = max_cache / n_indexes;
total_cache -= index_sizes.filter_index * n_indexes;
}
return {sizes, kernel::CacheSizes{static_cast<size_t>(nTotalCache)}};
return {index_sizes, kernel::CacheSizes{total_cache}};
}
} // namespace node
14 changes: 7 additions & 7 deletions src/node/caches.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
#define BITCOIN_NODE_CACHES_H

#include <kernel/caches.h>
#include <util/byte_units.h>

#include <cstddef>
#include <cstdint>

class ArgsManager;

//! min. -dbcache (MiB)
static constexpr int64_t MIN_DB_CACHE{4};
//! -dbcache default (MiB)
static constexpr int64_t DEFAULT_DB_CACHE{DEFAULT_KERNEL_CACHE};
//! min. -dbcache (bytes)
static constexpr size_t MIN_DB_CACHE{4_MiB};
//! -dbcache default (bytes)
static constexpr size_t DEFAULT_DB_CACHE{DEFAULT_KERNEL_CACHE};

namespace node {
struct IndexCacheSizes {
int64_t tx_index;
int64_t filter_index;
size_t tx_index;
size_t filter_index;
};
struct CacheSizes {
IndexCacheSizes index;
Expand Down
2 changes: 1 addition & 1 deletion src/node/chainstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static ChainstateLoadResult CompleteChainstateInitialization(
try {
pblocktree = std::make_unique<BlockTreeDB>(DBParams{
.path = chainman.m_options.datadir / "blocks" / "index",
.cache_bytes = static_cast<size_t>(cache_sizes.block_tree_db),
.cache_bytes = cache_sizes.block_tree_db,
.memory_only = options.block_tree_db_in_memory,
.wipe_data = options.wipe_block_tree_db,
.options = chainman.m_options.block_tree_db});
Expand Down
2 changes: 1 addition & 1 deletion src/qt/optionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
ui->verticalLayout->setStretchFactor(ui->tabWidget, 1);

/* Main elements init */
ui->databaseCache->setRange(MIN_DB_CACHE, std::numeric_limits<int>::max());
ui->databaseCache->setRange(MIN_DB_CACHE >> 20, std::numeric_limits<int>::max());
ui->threadsScriptVerif->setMinimum(-GetNumCores());
ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS);
ui->pruneWarning->setVisible(false);
Expand Down
4 changes: 2 additions & 2 deletions src/qt/optionsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con
suffix.empty() ? getOption(option, "-prev") :
DEFAULT_PRUNE_TARGET_GB;
case DatabaseCache:
return qlonglong(SettingToInt(setting(), DEFAULT_DB_CACHE));
return qlonglong(SettingToInt(setting(), DEFAULT_DB_CACHE >> 20));
case ThreadsScriptVerif:
return qlonglong(SettingToInt(setting(), DEFAULT_SCRIPTCHECK_THREADS));
case Listen:
Expand Down Expand Up @@ -733,7 +733,7 @@ void OptionsModel::checkAndMigrate()
// see https://github.com/bitcoin/bitcoin/pull/8273
// force people to upgrade to the new value if they are using 100MB
if (settingsVersion < 130000 && settings.contains("nDatabaseCache") && settings.value("nDatabaseCache").toLongLong() == 100)
settings.setValue("nDatabaseCache", (qint64)DEFAULT_DB_CACHE);
settings.setValue("nDatabaseCache", (qint64)(DEFAULT_DB_CACHE >> 20));

settings.setValue(strSettingsVersionKey, CLIENT_VERSION);
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/util/setup_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,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_kernel_cache_sizes.block_tree_db),
.cache_bytes = m_kernel_cache_sizes.block_tree_db,
.memory_only = true,
});
};
Expand Down
4 changes: 2 additions & 2 deletions src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -1067,11 +1067,11 @@ class ChainstateManager

//! The total number of bytes available for us to use across all in-memory
//! coins caches. This will be split somehow across chainstates.
int64_t m_total_coinstip_cache{0};
size_t m_total_coinstip_cache{0};
//
//! The total number of bytes available for us to use across all leveldb
//! coins databases. This will be split somehow across chainstates.
int64_t m_total_coinsdb_cache{0};
size_t m_total_coinsdb_cache{0};

//! Instantiate a new chainstate.
//!
Expand Down

0 comments on commit 45fe603

Please sign in to comment.