mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 06:43:45 +01:00
Merge bitcoin/bitcoin#31483: kernel: Move kernel-related cache constants to kernel cache
2a92702bafinit: Use size_t consistently for cache sizes (TheCharlatan)65cde3621dkernel: Move default cache constants to caches (TheCharlatan)8826cae285kernel: Move non-kernel db cache size constants (TheCharlatan)e758b26b85kernel: Move kernel-specific cache size options to kernel (TheCharlatan)d5e2c4a409fuzz: Add fuzz test for checked and saturating add and left shift (TheCharlatan)c03a2795a8util: Add integer left shift helpers (TheCharlatan)8bd5f8a38c[refactor] init: Simplify coinsdb cache calculation (TheCharlatan)5db7d4d3d2doc: Correct docstring describing max block tree db cache (TheCharlatan) Pull request description: Carrying non-kernel related fields in the cache sizes for the indexes is confusing for kernel library users. The cache sizes are set currently with magic numbers in bitcoin-chainstate. The comments for the cache size calculations are not completely clear. The constants for the cache sizes are also currently in `txdb.h`, which is not an ideal place for holding all cache size related constants. Solve these things by moving the kernel-specific cache size fields to their own struct and moving the constants to either the node or the kernel cache sizes. This slightly changes the way the cache is allocated if (and only 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 PR: ``` 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) ``` --- This PR is part of the [libbitcoinkernel project](https://github.com/bitcoin/bitcoin/issues/27587). ACKs for top commit: stickies-v: re-ACK2a92702bafryanofsky: Code review ACK2a92702baf. Changes since last review are fixing size options to use size_t instead of int64_t again, simplifying CheckedLeftShift more, and making other minor suggested cleanups hodlinator: re-ACK2a92702bafTree-SHA512: 98376eaa0660b1b8c096a5ce1f3e7c8c30e7cd6644de36856c2d3e573108cfc9473c93ebb3952b7881047b5ae6c85c5b096e6726f30f35be58b98eca07c8c785
This commit is contained in:
@@ -6,28 +6,39 @@
|
||||
|
||||
#include <common/args.h>
|
||||
#include <index/txindex.h>
|
||||
#include <txdb.h>
|
||||
#include <kernel/caches.h>
|
||||
#include <logging.h>
|
||||
#include <util/byte_units.h>
|
||||
|
||||
#include <algorithm>
|
||||
#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 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", 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;
|
||||
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;
|
||||
// Convert -dbcache from MiB units to bytes. The total cache is floored by MIN_DB_CACHE and capped by max size_t value.
|
||||
size_t total_cache{DEFAULT_DB_CACHE};
|
||||
if (std::optional<int64_t> db_cache = args.GetIntArg("-dbcache")) {
|
||||
if (*db_cache < 0) db_cache = 0;
|
||||
uint64_t db_cache_bytes = SaturatingLeftShift<uint64_t>(*db_cache, 20);
|
||||
total_cache = std::max<size_t>(MIN_DB_CACHE, std::min<uint64_t>(db_cache_bytes, std::numeric_limits<size_t>::max()));
|
||||
}
|
||||
sizes.coins_db = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache
|
||||
sizes.coins_db = std::min(sizes.coins_db, nMaxCoinsDBCache << 20); // cap total coins db cache
|
||||
nTotalCache -= sizes.coins_db;
|
||||
sizes.coins = nTotalCache; // the rest goes to in-memory cache
|
||||
return sizes;
|
||||
|
||||
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;
|
||||
if (n_indexes > 0) {
|
||||
size_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 {index_sizes, kernel::CacheSizes{total_cache}};
|
||||
}
|
||||
} // namespace node
|
||||
|
||||
@@ -5,18 +5,26 @@
|
||||
#ifndef BITCOIN_NODE_CACHES_H
|
||||
#define BITCOIN_NODE_CACHES_H
|
||||
|
||||
#include <kernel/caches.h>
|
||||
#include <util/byte_units.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class ArgsManager;
|
||||
|
||||
//! 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 {
|
||||
size_t tx_index{0};
|
||||
size_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
|
||||
|
||||
@@ -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().
|
||||
@@ -44,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});
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user