Skip to content

Commit e758b26

Browse files
committed
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)
1 parent d5e2c4a commit e758b26

File tree

10 files changed

+74
-44
lines changed

10 files changed

+74
-44
lines changed

src/bitcoin-chainstate.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,7 @@ int main(int argc, char* argv[])
123123
util::SignalInterrupt interrupt;
124124
ChainstateManager chainman{interrupt, chainman_opts, blockman_opts};
125125

126-
node::CacheSizes cache_sizes;
127-
cache_sizes.block_tree_db = 2 << 20;
128-
cache_sizes.coins_db = 2 << 22;
129-
cache_sizes.coins = (450 << 20) - (2 << 20) - (2 << 22);
126+
kernel::CacheSizes cache_sizes{nDefaultDbCache << 20};
130127
node::ChainstateLoadOptions options;
131128
auto [status, error] = node::LoadChainstate(chainman, cache_sizes, options);
132129
if (status != node::ChainstateLoadStatus::SUCCESS) {

src/init.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <interfaces/ipc.h>
3333
#include <interfaces/mining.h>
3434
#include <interfaces/node.h>
35+
#include <kernel/caches.h>
3536
#include <kernel/context.h>
3637
#include <key.h>
3738
#include <logging.h>
@@ -121,7 +122,6 @@ using common::ResolveErrMsg;
121122

122123
using node::ApplyArgsManOptions;
123124
using node::BlockManager;
124-
using node::CacheSizes;
125125
using node::CalculateCacheSizes;
126126
using node::ChainstateLoadResult;
127127
using node::ChainstateLoadStatus;
@@ -1177,7 +1177,7 @@ static ChainstateLoadResult InitAndLoadChainstate(
11771177
NodeContext& node,
11781178
bool do_reindex,
11791179
const bool do_reindex_chainstate,
1180-
CacheSizes& cache_sizes,
1180+
const kernel::CacheSizes& cache_sizes,
11811181
const ArgsManager& args)
11821182
{
11831183
const CChainParams& chainparams = Params();
@@ -1603,18 +1603,18 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
16031603
ReadNotificationArgs(args, kernel_notifications);
16041604

16051605
// cache size calculations
1606-
CacheSizes cache_sizes = CalculateCacheSizes(args, g_enabled_filter_types.size());
1606+
const auto [index_cache_sizes, kernel_cache_sizes] = CalculateCacheSizes(args, g_enabled_filter_types.size());
16071607

1608-
LogPrintf("Cache configuration:\n");
1609-
LogPrintf("* Using %.1f MiB for block index database\n", cache_sizes.block_tree_db * (1.0 / 1024 / 1024));
1608+
LogInfo("Cache configuration:");
1609+
LogInfo("* Using %.1f MiB for block index database", kernel_cache_sizes.block_tree_db * (1.0 / 1024 / 1024));
16101610
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1611-
LogPrintf("* Using %.1f MiB for transaction index database\n", cache_sizes.tx_index * (1.0 / 1024 / 1024));
1611+
LogInfo("* Using %.1f MiB for transaction index database", index_cache_sizes.tx_index * (1.0 / 1024 / 1024));
16121612
}
16131613
for (BlockFilterType filter_type : g_enabled_filter_types) {
1614-
LogPrintf("* Using %.1f MiB for %s block filter index database\n",
1615-
cache_sizes.filter_index * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
1614+
LogInfo("* Using %.1f MiB for %s block filter index database",
1615+
index_cache_sizes.filter_index * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
16161616
}
1617-
LogPrintf("* Using %.1f MiB for chain state database\n", cache_sizes.coins_db * (1.0 / 1024 / 1024));
1617+
LogInfo("* Using %.1f MiB for chain state database", kernel_cache_sizes.coins_db * (1.0 / 1024 / 1024));
16181618

16191619
assert(!node.mempool);
16201620
assert(!node.chainman);
@@ -1627,7 +1627,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
16271627
node,
16281628
do_reindex,
16291629
do_reindex_chainstate,
1630-
cache_sizes,
1630+
kernel_cache_sizes,
16311631
args);
16321632
if (status == ChainstateLoadStatus::FAILURE && !do_reindex && !ShutdownRequested(node)) {
16331633
// suggest a reindex
@@ -1646,7 +1646,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
16461646
node,
16471647
do_reindex,
16481648
do_reindex_chainstate,
1649-
cache_sizes,
1649+
kernel_cache_sizes,
16501650
args);
16511651
}
16521652
if (status != ChainstateLoadStatus::SUCCESS && status != ChainstateLoadStatus::INTERRUPTED) {
@@ -1672,12 +1672,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
16721672
// ********************************************************* Step 8: start indexers
16731673

16741674
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1675-
g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), cache_sizes.tx_index, false, do_reindex);
1675+
g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), index_cache_sizes.tx_index, false, do_reindex);
16761676
node.indexes.emplace_back(g_txindex.get());
16771677
}
16781678

16791679
for (const auto& filter_type : g_enabled_filter_types) {
1680-
InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, cache_sizes.filter_index, false, do_reindex);
1680+
InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, index_cache_sizes.filter_index, false, do_reindex);
16811681
node.indexes.emplace_back(GetBlockFilterIndex(filter_type));
16821682
}
16831683

src/kernel/caches.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) 2024-present The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_KERNEL_CACHES_H
6+
#define BITCOIN_KERNEL_CACHES_H
7+
8+
#include <util/byte_units.h>
9+
10+
#include <algorithm>
11+
12+
//! Max memory allocated to block tree DB specific cache (bytes)
13+
static constexpr size_t MAX_BLOCK_DB_CACHE{2_MiB};
14+
//! Max memory allocated to coin DB specific cache (bytes)
15+
static constexpr size_t MAX_COINS_DB_CACHE{8_MiB};
16+
17+
namespace kernel {
18+
struct CacheSizes {
19+
size_t block_tree_db;
20+
size_t coins_db;
21+
size_t coins;
22+
23+
CacheSizes(size_t total_cache)
24+
{
25+
block_tree_db = std::min(total_cache / 8, MAX_BLOCK_DB_CACHE);
26+
total_cache -= block_tree_db;
27+
coins_db = std::min(total_cache / 2, MAX_COINS_DB_CACHE);
28+
total_cache -= coins_db;
29+
coins = total_cache; // the rest goes to the coins cache
30+
}
31+
};
32+
} // namespace kernel
33+
34+
#endif // BITCOIN_KERNEL_CACHES_H

src/node/caches.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,25 @@
66

77
#include <common/args.h>
88
#include <index/txindex.h>
9+
#include <kernel/caches.h>
910
#include <txdb.h>
1011

12+
#include <algorithm>
13+
#include <string>
14+
1115
namespace node {
1216
CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes)
1317
{
1418
int64_t nTotalCache = (args.GetIntArg("-dbcache", nDefaultDbCache) << 20);
1519
nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache
16-
CacheSizes sizes;
17-
sizes.block_tree_db = std::min(nTotalCache / 8, nMaxBlockDBCache << 20);
18-
nTotalCache -= sizes.block_tree_db;
20+
IndexCacheSizes sizes;
1921
sizes.tx_index = std::min(nTotalCache / 8, args.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxTxIndexCache << 20 : 0);
2022
nTotalCache -= sizes.tx_index;
21-
sizes.filter_index = 0;
2223
if (n_indexes > 0) {
2324
int64_t max_cache = std::min(nTotalCache / 8, max_filter_index_cache << 20);
2425
sizes.filter_index = max_cache / n_indexes;
2526
nTotalCache -= sizes.filter_index * n_indexes;
2627
}
27-
sizes.coins_db = std::min(nTotalCache / 2, nMaxCoinsDBCache << 20);
28-
nTotalCache -= sizes.coins_db;
29-
sizes.coins = nTotalCache; // the rest goes to in-memory cache
30-
return sizes;
28+
return {sizes, kernel::CacheSizes{static_cast<size_t>(nTotalCache)}};
3129
}
3230
} // namespace node

src/node/caches.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,21 @@
55
#ifndef BITCOIN_NODE_CACHES_H
66
#define BITCOIN_NODE_CACHES_H
77

8+
#include <kernel/caches.h>
9+
810
#include <cstddef>
911
#include <cstdint>
1012

1113
class ArgsManager;
1214

1315
namespace node {
16+
struct IndexCacheSizes {
17+
int64_t tx_index{0};
18+
int64_t filter_index{0};
19+
};
1420
struct CacheSizes {
15-
int64_t block_tree_db;
16-
int64_t coins_db;
17-
int64_t coins;
18-
int64_t tx_index;
19-
int64_t filter_index;
21+
IndexCacheSizes index;
22+
kernel::CacheSizes kernel;
2023
};
2124
CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes = 0);
2225
} // namespace node

src/node/chainstate.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
#include <chain.h>
99
#include <coins.h>
1010
#include <consensus/params.h>
11+
#include <kernel/caches.h>
1112
#include <logging.h>
1213
#include <node/blockstorage.h>
13-
#include <node/caches.h>
1414
#include <sync.h>
1515
#include <threadsafety.h>
1616
#include <tinyformat.h>
@@ -29,6 +29,8 @@
2929
#include <memory>
3030
#include <vector>
3131

32+
using kernel::CacheSizes;
33+
3234
namespace node {
3335
// Complete initialization of chainstates after the initial call has been made
3436
// to ChainstateManager::InitializeChainstate().

src/node/chainstate.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
class CTxMemPool;
1616

17-
namespace node {
18-
17+
namespace kernel {
1918
struct CacheSizes;
19+
} // namespace kernel
20+
21+
namespace node {
2022

2123
struct ChainstateLoadOptions {
2224
CTxMemPool* mempool{nullptr};
@@ -69,7 +71,7 @@ using ChainstateLoadResult = std::tuple<ChainstateLoadStatus, bilingual_str>;
6971
*
7072
* LoadChainstate returns a (status code, error string) tuple.
7173
*/
72-
ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes,
74+
ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const kernel::CacheSizes& cache_sizes,
7375
const ChainstateLoadOptions& options);
7476
ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options);
7577
} // namespace node

src/test/util/setup_common.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ using kernel::BlockTreeDB;
6666
using node::ApplyArgsManOptions;
6767
using node::BlockAssembler;
6868
using node::BlockManager;
69-
using node::CalculateCacheSizes;
7069
using node::KernelNotifications;
7170
using node::LoadChainstate;
7271
using node::RegenerateCommitments;
@@ -228,8 +227,6 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts)
228227
Assert(error.empty());
229228
m_node.warnings = std::make_unique<node::Warnings>();
230229

231-
m_cache_sizes = CalculateCacheSizes(m_args);
232-
233230
m_node.notifications = std::make_unique<KernelNotifications>(Assert(m_node.shutdown_request), m_node.exit_status, *Assert(m_node.warnings));
234231

235232
m_make_chainman = [this, &chainparams, opts] {
@@ -255,7 +252,7 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts)
255252
LOCK(m_node.chainman->GetMutex());
256253
m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<BlockTreeDB>(DBParams{
257254
.path = m_args.GetDataDirNet() / "blocks" / "index",
258-
.cache_bytes = static_cast<size_t>(m_cache_sizes.block_tree_db),
255+
.cache_bytes = static_cast<size_t>(m_kernel_cache_sizes.block_tree_db),
259256
.memory_only = true,
260257
});
261258
};
@@ -291,7 +288,7 @@ void ChainTestingSetup::LoadVerifyActivateChainstate()
291288
options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
292289
options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
293290
options.require_full_verification = m_args.IsArgSet("-checkblocks") || m_args.IsArgSet("-checklevel");
294-
auto [status, error] = LoadChainstate(chainman, m_cache_sizes, options);
291+
auto [status, error] = LoadChainstate(chainman, m_kernel_cache_sizes, options);
295292
assert(status == node::ChainstateLoadStatus::SUCCESS);
296293

297294
std::tie(status, error) = VerifyLoadedChainstate(chainman, options);

src/test/util/setup_common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define BITCOIN_TEST_UTIL_SETUP_COMMON_H
77

88
#include <common/args.h> // IWYU pragma: export
9+
#include <kernel/caches.h>
910
#include <kernel/context.h>
1011
#include <key.h>
1112
#include <node/caches.h>
@@ -103,7 +104,7 @@ struct BasicTestingSetup {
103104
* initialization behaviour.
104105
*/
105106
struct ChainTestingSetup : public BasicTestingSetup {
106-
node::CacheSizes m_cache_sizes{};
107+
kernel::CacheSizes m_kernel_cache_sizes{node::CalculateCacheSizes(m_args).kernel};
107108
bool m_coins_db_in_memory{true};
108109
bool m_block_tree_db_in_memory{true};
109110
std::function<void()> m_make_chainman{};

src/txdb.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,12 @@ static const int64_t nDefaultDbCache = 450;
2727
static const int64_t nDefaultDbBatchSize = 16 << 20;
2828
//! min. -dbcache (MiB)
2929
static const int64_t nMinDbCache = 4;
30-
//! Max memory allocated to block tree DB specific cache (MiB)
31-
static const int64_t nMaxBlockDBCache = 2;
3230
// Unlike for the UTXO database, for the txindex scenario the leveldb cache make
3331
// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
3432
//! Max memory allocated to tx index DB specific cache in MiB.
3533
static const int64_t nMaxTxIndexCache = 1024;
3634
//! Max memory allocated to all block filter index caches combined in MiB.
3735
static const int64_t max_filter_index_cache = 1024;
38-
//! Max memory allocated to coin DB specific cache (MiB)
39-
static const int64_t nMaxCoinsDBCache = 8;
4036

4137
//! User-controlled performance and debug options.
4238
struct CoinsViewOptions {

0 commit comments

Comments
 (0)